Stop hook receives malformed JSON stdin on Windows with non-ASCII assistant message

Open 💬 1 comment Opened May 21, 2026 by kcrazy

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.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗