Repository navigation
Fix #138: Force UTF-8 on agent subprocess pipes on Windows - #336
zwanski-start wants to merge 1 commit into
Conversation
The orchestrator already decoded child output as UTF-8 with errors=replace, but Python children still encoded their piped stdout with the Windows ANSI code page (CP1252). Set PYTHONIOENCODING=utf-8 for every agent subprocess (parallel orchestrator and the server's process manager) so both ends agree, and decode claude CLI stderr in start.py as UTF-8 instead of the locale codec. Adds test_subprocess_encoding.py covering the spawn kwargs, a non-ASCII round trip, and invalid bytes such as the 0x8f from the report. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🔍 QA report: ✅ PassedTester: Ken (cubefarm agent, in a fresh session) · Round: 1 · Author: Barbara The PR sets PYTHONIOENCODING=utf-8 on every agent subprocess (coding, batch, testing and initializer spawns in parallel_orchestrator.py, plus the orchestrator spawn in process_manager.py), so the child now writes UTF-8 to match the UTF-8 reader the parent already had. It also decodes claude CLI stderr in start.py as UTF-8 with replace. A real-child probe with a simulated CP1252 environment raises UnicodeEncodeError on master and passes cleanly on this branch. Lint, security tests, the 6 new tests and the UI build all pass, and the full pytest suite has the same 21 failures as master (pytest-asyncio is missing from this venv), so nothing regressed.
🧪 Commands run
No browser screenshots were taken in this round. Posted by cubefarm · merges automatically once GitHub's checks pass |
Problem
On Windows, the parallel orchestrator's output reader thread crashed with
UnicodeDecodeError: 'charmap' codec can't decode byte 0x8fbecause subprocess pipes defaulted to the ANSI code page (CP1252).What changed
The issue's suggested fix (
encoding="utf-8",errors="replace"on the orchestrator'sPopencalls) is already onmaster. The server's process manager, dev server manager and scaffold router also decode bytes as UTF-8 withreplace. One gap was left: the children still wrote CP1252. A Python child whose stdout is a pipe on Windows encodes output with the locale code page. So non-ASCII agent output either raisedUnicodeEncodeErrorin the child or showed up as�garbage once the parent decoded it as UTF-8.parallel_orchestrator.py: every agent subprocess (coding, coding batch, testing, initializer) now getsPYTHONIOENCODING=utf-8, so both ends of the pipe use UTF-8.server/services/process_manager.py: the orchestrator process started from the UI gets the same setting.start.py: the twosubprocess.run(..., stderr=PIPE, text=True)calls that readclaudeCLI stderr now decode as UTF-8 witherrors="replace"instead of the locale codec.test_subprocess_encoding.py(6 tests). It checks thePopenkwargs and env for the coding, batch and testing spawns, including when the parent env forces CP1252. It also runs a real non-ASCII round trip through a child and checks that invalid bytes such as the reported0x8fare replaced instead of raising. Added to the test list inCLAUDE.md.Verification
pytest test_client.py test_dependency_resolver.py test_rate_limit_utils.py test_subprocess_encoding.py: 61 passedpython test_security.py: all passedruff check .: clean;mypyreports no errors in the touched files (the errors it does report are pre-existing ones in other modules)PYTHONIOENCODING=cp1252in the parent env.Assumptions
PYTHONIOENCODING=utf-8rather thanPYTHONUTF8=1. UTF-8 mode would also change the default encoding foropen()in agent processes, which is a bigger behaviour change than this fix needs.Closes #138
🤖 Generated with Claude Code