claude-code - 💡(How to fix) Fix Persistent 400 'thinking blocks in the latest assistant message cannot be modified' — interleaved thinking persisted with empty text + signature bricks sessions

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Under extended/interleaved thinking, any assistant turn that interleaves thinking with multiple tool calls gets persisted to the session JSONL with its thinking blocks emptied ("thinking": "") while the signature is retained. On the next request the API rejects the replayed (now-modified) thinking blocks with:

API Error: 400 messages.<N>.content.<M>: `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 every subsequent request replays the same poisoned turn, the session dies on every turn and is unrecoverable without manually editing the transcript.

Error Message

API Error: 400 messages.<N>.content.<M>: 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

Because every subsequent request replays the same poisoned turn, the session dies on every turn and is unrecoverable without manually editing the transcript.

Fix Action

Fix / Workaround

Workaround (no config change, no loss of thinking)

Fully exit the session, then remove only the interior thinking blocks from the JSONL (keep the legitimate leading thinking block of each turn; the removed blocks are already empty so no reasoning is lost), repointing any parentUuid that referenced a removed record. After that the session resumes cleanly. Disabling thinking is not required and is not an acceptable workaround for deep-reasoning workflows.

Code Example

API Error: 400 messages.<N>.content.<M>: `thinking` or `redacted_thinking` blocks in the latest assistant message cannot be modified. These blocks must remain as they were in the original response.
RAW_BUFFERClick to expand / collapse

Summary

Under extended/interleaved thinking, any assistant turn that interleaves thinking with multiple tool calls gets persisted to the session JSONL with its thinking blocks emptied ("thinking": "") while the signature is retained. On the next request the API rejects the replayed (now-modified) thinking blocks with:

API Error: 400 messages.<N>.content.<M>: `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 every subsequent request replays the same poisoned turn, the session dies on every turn and is unrecoverable without manually editing the transcript.

Environment

  • Claude Code 2.1.154
  • Model: Opus (claude-opus-4-7), adaptive thinking with CLAUDE_EFFORT=xhigh
  • Platform: WSL2 (Linux 6.6 / Ubuntu), Node v24.14.0
  • Sessions persisted as JSONL under ~/.claude/projects/<project>/<id>.jsonl

Impact

High. A single affected turn bricks the entire session — resume reloads the same broken message and 400s again. The only recovery is hand-editing the transcript.

Reproduction

  1. Run a session with high effort / interleaved thinking on Opus.
  2. Have the assistant do a turn that interleaves thinking with several tool calls (e.g. a handful of Bash calls with reasoning between them). Reliably reproduces on a brand-new, clean session within the first assistant turn — observed crashing at messages.1.content.9.
  3. The next request fails with the 400 above; every retry/resume fails identically.

Root-cause evidence (from inspecting the JSONL)

  • All thinking blocks on disk have empty text + a signature: in one affected transcript, 909/909 thinking blocks had "thinking": "" (len 0) with a populated signature.
  • The crash is specific to interleaved thinking: turns whose thinking block sits at a non-leading position within the assistant turn (a thinking block emitted after a tool_use, all sharing one message.id / requestId). In a 1332-turn transcript, exactly the turns with such interior thinking blocks were corrupt; turns with only a single leading thinking block replay fine.
  • On disk these turns appear as many assistant entries sharing one requestId, with a block sequence like [thinking, text, tool_use, tool_use, …, thinking, tool_use, …, thinking] — the interior/trailing thinking entries are the ones flagged by content.<M>.
  • The error's content.<M> index lands on one of these interior thinking blocks; messages.<N> is the position of that turn in the replayed request.

So: the harness empties the thinking text but keeps the signature, and the API's "thinking blocks must be unmodified" constraint then rejects the interleaved blocks on replay. A single leading thinking block is tolerated; the interleaved case is where it surfaces.

Suggested fix (harness side)

When replaying prior assistant turns, either:

  • (a) preserve the original thinking text alongside the signature for blocks that must be sent back, or
  • (b) drop thinking blocks from replayed assistant messages entirely rather than sending empty-text stubs with signatures.

Emptying the text while keeping the signature is the broken middle ground.

Workaround (no config change, no loss of thinking)

Fully exit the session, then remove only the interior thinking blocks from the JSONL (keep the legitimate leading thinking block of each turn; the removed blocks are already empty so no reasoning is lost), repointing any parentUuid that referenced a removed record. After that the session resumes cleanly. Disabling thinking is not required and is not an acceptable workaround for deep-reasoning workflows.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING