Skip to content

SessionStart writes two JSON documents to stdout when two notices apply; Claude Code 2.1.278 shows a red hook error #43

Description

@davidcrowe

What happened

On a fresh Claude Code 2.1.278 session with plugin 0.21.0, the TUI showed a red startup error on every screen:

SessionStart:startup hook error
Hook output looks like a JSON object but is not valid JSON — JSON Parse error: Unable to parse JSON string. Emit the payload with a JSON encoder (jq, ConvertTo-Json, json.dumps) rather than string concatenation so backslashes and quotes inside strings are escaped.

The hook's raw stdout for that SessionStart, from the session transcript, was two JSON documents back to back:

{"systemMessage":"[ACP] 7 tool calls recorded while ACP could not see them (offline, or before this key was connected) are uploading once now; they will appear in your audit with their original timestamps."}{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":"[ACP] Governance plugin claude-code-plugin v0.21.0 is outdated — v0.25.0 is current. ..."}}

Each write on its own is valid. Concatenated they are not, and Claude Code parses the hook's whole stdout as one document.

When it happens

Any SessionStart where more than one notice applies in the same run of govern.mjs: here the offline-ledger flush notice (0.16.0) plus the stale-plugin notice (0.21.0). Other pairs of process.stdout.write(JSON.stringify(...)) on the same event would do the same.

Effect

The error is cosmetic for enforcement (PreToolUse still ran and denied the force-push in the same session), but both notices are lost, the session shows a red hook error on every screen, and it is the first thing a new user sees after install.

Fix shape

One stdout write per hook invocation: collect notices, then emit a single object with systemMessage and hookSpecificOutput together (Claude Code accepts both fields in one document). A guard in the test suite that a hook run never writes to stdout twice would catch the next pair.

Seen 2026-09-21 in session 15895bcc-45b6-4cfe-8372-4859beb255be (tenant dcroweua). Not yet checked whether 0.25.0 still has both writes.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions