[BUG] Stop hook blocks with 'continue: true' fail with API error when response contains thinking blocks
Bug Description
When a stop hook returns {"decision": "block", "continue": true, "reason": "..."}, Claude Code attempts to inject the reason message into the assistant's previous response. This fails with an API error when that response contains thinking blocks.
Error Message
API Error: 400 {"type":"error","error":{"type":"invalid_request_error","message":"messages.19.content.18: \`thinking\` or \`redacted_thinking\` blocks in the latest assistant message cannot be modified. These blocks must remain as they were in the original response."}}
Root Cause
- Stop hook executes and returns block decision with
continue: true - Claude Code attempts to inject the reason message by modifying the assistant's last message
- API correctly prohibits modification of thinking blocks (they are immutable after generation)
- Injection fails and creates retry loop
Expected Behavior
When a stop hook blocks with continue: true, the reason message should be delivered without modifying the assistant's message. Options:
- Deliver as separate system message
- Detect thinking blocks and use alternative injection mechanism
- Append without modifying existing content blocks
Actual Behavior
Claude Code tries to modify the assistant message containing thinking blocks, API rejects with 400 error, creates retry loop.
Environment
- Stop hook configuration: Valid JSON output with decision/continue/reason fields
- Thinking mode: interleaved
- Hook output validated with bash -n (syntactically correct)
Workaround
None available from stop hook side - this requires fix in Claude Code's hook processing logic.
Related Issues
Possibly related to #9486 (system-reminder injection breaking thinking blocks)
Reproduction
- Configure stop hook that returns
{"decision": "block", "continue": true, "reason": "test"} - Generate assistant response with thinking blocks
- Stop hook fires and attempts injection
- Observe API 400 error about thinking blocks cannot be modified
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗