Summary
When extended/interleaved thinking is enabled in Claude Code, RTK's PreToolUse
hook (rtk hook claude) appears to mutate the assistant message while rewriting a
tool call. If that assistant message also contains a thinking block, the next
API request is rejected by Anthropic with:
API Error: 400 messages.1.content.13: thinking or redacted_thinking blocks in the latest assistant message cannot be modified. These blocks must remain as they were in the original response.
Because the corrupted message stays in conversation history, every subsequent turn
re-sends it and fails identically — the session is hard-locked and unrecoverable
without removing the message.
Why I believe RTK is involved
- RTK is registered as
PreToolUse -> rtk hook claude (rewrites tool calls before they run).
- The failure only occurs on long, tool-heavy turns where interleaved thinking
produces an assistant message that mixes thinking blocks with multiple tool_use
blocks (the API error referenced content.13, i.e. a thinking block among the tool calls).
- Anthropic requires
thinking/redacted_thinking blocks to be returned byte-for-byte
unchanged. A PreToolUse hook that rewrites the tool_use inside that same message is
the most direct candidate for breaking that invariant.
Steps to reproduce
- Use Claude Code with extended/interleaved thinking enabled.
- Install RTK and let it register its
PreToolUse hook (rtk hook claude).
- Give the agent a task that triggers many bash tool calls in a single turn
(e.g. a multi-step debugging task that runs ~15+ commands) so thinking blocks
and tool_use blocks interleave in one assistant message.
- Observe the API 400 error above. The session then fails on every retry.
Expected behavior
Rewriting a tool command should never alter sibling thinking/redacted_thinking
blocks (or cause them to be re-serialized in a way that changes their signature).
Thinking blocks must be passed through untouched.
Actual behavior
The thinking block in the latest assistant message is treated as modified by the
Anthropic API, producing a 400 and locking the session.
Environment
- RTK version: 0.38.0 at time of failure (also reproduced conceptually on 0.42.0; no
thinking-related fix found in 0.42.0 changelog)
- Install method: Homebrew (
/opt/homebrew/bin/rtk)
- OS: macOS (Darwin 24.3.0)
- Client: Claude Code (Anthropic), model: Claude Opus 4.x, interleaved thinking enabled
- Hook config (from ~/.claude/settings.json):
SessionStart -> ~/.claude/hooks/rtk-ensure-hook.sh
PreToolUse -> rtk hook claude
Suggested fix / mitigation
When processing the PreToolUse payload, RTK should treat any thinking /
redacted_thinking content as immutable and pass it through verbatim, ensuring no
re-serialization of the assistant message alters those blocks. A regression test that
runs the hook against an assistant message containing interleaved thinking + tool_use
blocks and asserts the thinking blocks are byte-identical afterward would catch this.
Summary
When extended/interleaved thinking is enabled in Claude Code, RTK's
PreToolUsehook (
rtk hook claude) appears to mutate the assistant message while rewriting atool call. If that assistant message also contains a
thinkingblock, the nextAPI request is rejected by Anthropic with:
API Error: 400 messages.1.content.13: thinking or redacted_thinking blocks in the latest assistant message cannot be modified. These blocks must remain as they were in the original response.Because the corrupted message stays in conversation history, every subsequent turn
re-sends it and fails identically — the session is hard-locked and unrecoverable
without removing the message.
Why I believe RTK is involved
PreToolUse -> rtk hook claude(rewrites tool calls before they run).produces an assistant message that mixes
thinkingblocks with multipletool_useblocks (the API error referenced
content.13, i.e. a thinking block among the tool calls).thinking/redacted_thinkingblocks to be returned byte-for-byteunchanged. A PreToolUse hook that rewrites the
tool_useinside that same message isthe most direct candidate for breaking that invariant.
Steps to reproduce
PreToolUsehook (rtk hook claude).(e.g. a multi-step debugging task that runs ~15+ commands) so thinking blocks
and tool_use blocks interleave in one assistant message.
Expected behavior
Rewriting a tool command should never alter sibling
thinking/redacted_thinkingblocks (or cause them to be re-serialized in a way that changes their signature).
Thinking blocks must be passed through untouched.
Actual behavior
The thinking block in the latest assistant message is treated as modified by the
Anthropic API, producing a 400 and locking the session.
Environment
thinking-related fix found in 0.42.0 changelog)
/opt/homebrew/bin/rtk)SessionStart -> ~/.claude/hooks/rtk-ensure-hook.shPreToolUse -> rtk hook claudeSuggested fix / mitigation
When processing the PreToolUse payload, RTK should treat any
thinking/redacted_thinkingcontent as immutable and pass it through verbatim, ensuring nore-serialization of the assistant message alters those blocks. A regression test that
runs the hook against an assistant message containing interleaved thinking + tool_use
blocks and asserts the thinking blocks are byte-identical afterward would catch this.