You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
A Parent Pinned to UTF-8 Spawning a Python Child Leaves the Child's Encoder on the Locale #1577
#1574 pins encoding="utf-8" on every text-mode subprocess call in this repository, so a parent decodes its child as UTF-8 on every host. Where that child is another Python interpreter, its own encoder is still the locale's, and the two sides now disagree on Windows in a way they did not before.
Before that change both sides took the locale codec, so they matched, whatever the locale was. After it the parent names UTF-8 while a redirected Python child on Windows writes its stdout in the ANSI code page, so any non-ASCII character the child prints comes back as a byte sequence the parent cannot decode.
Around fourteen call sites spawn sys.executable this way, in host-setup/agent-safety/claude/test_install.py, scripts/tests/test_build_dist.py, scripts/tests/test_prose_lint.py and scripts/tests/test_spec_validate.py.
Evidence
Constructed, using an environment variable to stand in for a Windows ANSI host, since the fleet has no Windows runner:
subprocess.run([sys.executable, <a script that prints a path>],
text=True, encoding="utf-8",
env={..., "PYTHONIOENCODING": "cp1252"})
-> UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe9
The child prints a path holding a non-ASCII character, encodes it as cp1252, and the parent decodes as UTF-8.
Reach
A test run on a Windows host, which is the platform GOVERNANCE.md "Supported Development Platforms" declares supported and which nothing in CI exercises. A Linux run is unaffected, since both sides resolve to UTF-8 anyway.
One site in the tree already guards this, test_a_filename_that_is_not_utf8_is_scanned_and_reported in scripts/tests/test_prose_lint.py, by passing PYTHONIOENCODING=utf-8 to the child. So the mechanism is known and applied in one place rather than as a rule.
Suggested fix
Decide the rule, then apply it and assert it. A parent that pins its decoder and spawns a Python child owes that child the matching encoder, PYTHONIOENCODING=utf-8 being the one that reaches every output stream. scripts/tests/test_tooling_encoding.py asserts the parent half of this invariant already and is where the child half belongs.
Sibling of #1538. Found by a local review pass on #1574.
Partly addressed by #2523, from the child's side: spec/validate.py now reconfigures its own stdout and stderr to UTF-8 at the top of main, as scripts/pr_review.py already did. A cp1252 regression case in tests/test_spec_validate.py pins it on every host. So the test_spec_validate call sites named here now decode cleanly on Windows. The full suite at develop's head passed on a Windows host from Git Bash (2245 tests, OK). The other named sites print nothing non-ASCII in the current suite, so this issue's general fix is still open: a child-side reconfigure, or PYTHONIOENCODING=utf-8 on the spawn.
Activity
Promote develop to main: Name the Encoding on Every Text-Mode Subproc…
ptr727 commentedon Oct 8, 2026
Partly addressed by #2523, from the child's side:
spec/validate.pynow reconfigures its own stdout and stderr to UTF-8 at the top ofmain, asscripts/pr_review.pyalready did. A cp1252 regression case intests/test_spec_validate.pypins it on every host. So thetest_spec_validatecall sites named here now decode cleanly on Windows. The full suite atdevelop's head passed on a Windows host from Git Bash (2245 tests,OK). The other named sites print nothing non-ASCII in the current suite, so this issue's general fix is still open: a child-side reconfigure, orPYTHONIOENCODING=utf-8on the spawn.