Skip to content

PreToolUse hook (rtk hook claude) corrupts interleaved thinking blocks → Anthropic API 400 "thinking blocks cannot be modified", hard-locking the session #2146

@itspokchop93

Description

@itspokchop93

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

  1. Use Claude Code with extended/interleaved thinking enabled.
  2. Install RTK and let it register its PreToolUse hook (rtk hook claude).
  3. 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.
  4. 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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions