Stop hook receives malformed JSON stdin on Windows with non-ASCII assistant message
Environment
- Codex CLI: 0.132.0
- OS: Windows
- Shell: PowerShell
- Model: gpt-5.5
- Hook type: Stop
- Node.js: v24.14.0
- Hook target in this setup: oh-my-codex v0.18.0
Summary
On Windows, Codex sometimes invokes a Stop hook with malformed JSON on stdin. The JSON is already invalid before the hook implementation runs.
This is related to, but distinct from, #18887. That issue is about Codex's error reporting for invalid Stop hook output. This report is about the input payload sent by Codex to the Stop hook being malformed before the hook can parse it.
Observed behavior
A local PowerShell wrapper captured the raw stdin before passing it to the hook process. The captured payload starts as normal JSON and includes fields like:
session_idturn_idtranscript_pathcwdhook_event_name: "Stop"modelpermission_modestop_hook_activelast_assistant_message
But last_assistant_message contains mojibake/non-ASCII assistant output and the JSON string is not closed before the final }.
PowerShell parsing fails with:
Unterminated string passed in.
Node parsing also fails with an unterminated string error when the same captured stdin is replayed.
A sanitized shape of the malformed payload looks like:
{"session_id":"...","turn_id":"...","transcript_path":"...","cwd":"...","hook_event_name":"Stop","model":"gpt-5.5","permission_mode":"default","stop_hook_active":false,"last_assistant_message":"[mojibake/truncated non-ASCII assistant text]...}
Notice that last_assistant_message is not terminated as a JSON string.
Expected behavior
Codex should always serialize hook stdin as valid JSON, regardless of message language, encoding, or truncation.
Impact
Stop hooks that parse stdin fail before hook logic can run. In my case this eventually surfaced in the Codex UI as:
Stop hook (failed): hook returned invalid stop hook JSON output
The secondary UI error happened because the downstream hook returned a diagnostic object that is not accepted by the Stop output schema. However, the root issue is that the stdin payload from Codex was already malformed.
Additional notes
- Normal Stop hook payloads with small/ASCII
last_assistant_messageparse successfully and return{}. - A different Stop payload with
last_assistant_messagecontaining a short escaped JSON string also parses successfully. - The failure correlates with Chinese/non-ASCII assistant output becoming mojibake and being truncated inside
last_assistant_message. - I can provide a redacted raw capture if needed, but I avoided posting the full captured conversation content in this issue.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗