Skip to content

RunSkillScriptTool shell output can fail to decode on Windows locale defaults #6289

Description

@VectorPeak

What happened?

RunSkillScriptTool generates a Python wrapper when executing shell-based skill scripts. In the shell script path, the generated wrapper currently uses:

subprocess.run(..., capture_output=True, text=True)

without passing an explicit encoding or errors policy.

Because captured stdout/stderr are read in text mode, decoding can depend on the platform default text encoding when no encoding is supplied. On Windows environments using a non-UTF-8 default encoding such as cp936/gbk, UTF-8 bytes emitted by bash or a shell script can fail while subprocess is reading the captured stream.

In a local Windows full unit-test run, this appeared as:

UnicodeDecodeError: 'gbk' codec can't decode byte 0xff in position 47: illegal multibyte sequence

The failure caused the generated shell wrapper to lose the captured stderr path. Existing shell integration tests that expected stderr to map to warning or error instead observed success.

Affected path

RunSkillScriptTool.run_async()
  -> _SkillScriptCodeExecutor.execute_script_async()
    -> generated Python wrapper
      -> shell script branch for .sh / .bash files
        -> subprocess.run(..., capture_output=True, text=True)
        -> JSON shell result envelope
      -> RunSkillScriptTool parses stdout/stderr/returncode
      -> result status becomes success / warning / error

Expected behavior

The generated wrapper should decode captured shell stdout/stderr with a stable encoding policy so locale differences do not prevent the wrapper from returning the JSON shell-result envelope.

Suggested fix

Use explicit UTF-8 decoding with replacement error handling for shell wrapper subprocess output:

subprocess.run(
    ...,
    capture_output=True,
    text=True,
    encoding=utf-8,
    errors=replace,
    ...
)

This keeps the existing text-mode behavior while avoiding locale-dependent decode failures. Invalid non-UTF-8 byte sequences can be represented with replacement characters so the wrapper can still return stdout, stderr, and return code to the caller.

Notes

This does not attempt to preserve arbitrary legacy-encoded shell output byte-for-byte. It is intended to make generated shell wrapper output handling stable for UTF-8 skill scripts/resources across platforms.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions