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_id
turn_id
transcript_path
cwd
hook_event_name: "Stop"
model
permission_mode
stop_hook_active
last_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_message parse successfully and return {}.
- A different Stop payload with
last_assistant_message containing 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.
Environment
Summary
On Windows, Codex sometimes invokes a
Stophook 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_messageBut
last_assistant_messagecontains mojibake/non-ASCII assistant output and the JSON string is not closed before the final}.PowerShell parsing fails with:
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_messageis 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:
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
last_assistant_messageparse successfully and return{}.last_assistant_messagecontaining a short escaped JSON string also parses successfully.last_assistant_message.