claude-code - 💡(How to fix) Fix [BUG] Unrecoverable `400 … thinking/redacted_thinking blocks … cannot be modified` permanently bricks a session — reproduced across two independent sessions (v2.1.154)

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…

Error Message

Session 1:

API Error: 400 messages.7.content.4: thinking or redacted_thinking blocks in the latest assistant message cannot be modified. These blocks must remain as they were in the original response.

Session 2 (clean start, no resume — same error class, different coordinate):

API Error: 400 messages.1.content.35: thinking or redacted_thinking blocks in the latest assistant message cannot be modified. These blocks must remain as they were in the original response.

Code Example

Session 1:

API Error: 400 messages.7.content.4: `thinking` or `redacted_thinking` blocks in the latest assistant message cannot be modified. These blocks must remain as they were in the original response.


Session 2 (clean start, no resume — same error class, different coordinate):

API Error: 400 messages.1.content.35: `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

Preflight Checklist

  • I have searched existing issues and this hasn't been reported yet
  • This is a single bug report (please file separate reports for different bugs)
  • I am using the latest version of Claude Code

What's Wrong?

A Claude Code session entered a permanently unrecoverable state. Every message send fails with a 400 … thinking or redacted_thinking blocks in the latest assistant message cannot be modified error, and it never clears — every subsequent request in that conversation throws the same 400. There is no in-session recovery; the session is dead and any in-progress context is stranded.

This is not isolated to one corrupted transcript. The failure was reproduced in a second, freshly-started session that used no --resume and shared no transcript state with the first. The second session threw the same error class at a different coordinate (messages.1.content.35 vs. the first session's messages.7.content.4) — i.e., two independently-generated 400s, not one echoed error.

Both sessions were on v2.1.154 and both involved interleaved thinking (multiple signed thinking blocks within a single assistant turn) plus background sub-agents (Task/Agent tool, one continued mid-task / "resumed from transcript"). This points to a client-side bug in how Claude Code assembles/serializes signed thinking blocks into the outgoing API payload — the block sent no longer matches what the API originally signed, so the API rejects it.

Forensic detail supporting "send-time assembly, not on-disk state": the error's messages.N.content.M coordinates do not map to any on-disk transcript line where content[M] is actually a thinking block, meaning the request array sent to the API is assembled differently from the persisted transcript.

What Should Happen?

Signed thinking/redacted_thinking blocks should be preserved byte-for-byte through every request-assembly path — including background-sub-agent resume, context compaction, and long-idle resends — so they always match what the API signed.

Failing that, Claude Code should detect a thinking-block signature mismatch and self-heal (e.g., drop or regenerate the offending assistant turn) rather than looping on a fatal 400 that permanently bricks the session with no recovery path.

Error Messages/Logs

Session 1:

API Error: 400 messages.7.content.4: `thinking` or `redacted_thinking` blocks in the latest assistant message cannot be modified. These blocks must remain as they were in the original response.


Session 2 (clean start, no resume — same error class, different coordinate):

API Error: 400 messages.1.content.35: `thinking` or `redacted_thinking` blocks in the latest assistant message cannot be modified. These blocks must remain as they were in the original response.

Steps to Reproduce

I do not have a minimal deterministic repro, but both observed failures shared these conditions:

  1. Run a session that uses interleaved thinking (more than one signed thinking block per assistant turn).
  2. Have the session spawn a background sub-agent (Task/Agent tool), and/or continue/resume a background sub-agent mid-task ("resumed from transcript").
  3. Let the session sit idle for an extended period before the next send (the first failure followed a ~90-minute idle gap).
  4. Send the next message → it fails with 400 … thinking blocks … cannot be modified, and every send thereafter throws the same 400 permanently.

The fact that a second, completely fresh session (no resume, no shared state) reproduced the same error class on its own first substantial assistant turn suggests the trigger is in the request-assembly path rather than any single saved conversation.

Claude Model

Opus

Is this a regression?

Yes, this worked in a previous version

Last Working Version

2.1.152

Claude Code Version

2.1.154

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

One earlier hypothesis ruled out (so triage doesn't chase it): On disk, every thinking block in both broken transcripts is stored with a valid signature but empty plaintext ("thinking":""). This looked like the corruption, but a control comparison against three healthy sessions shows they store thinking blocks identically — it's the normal on-disk convention (full text held in memory, only the signature persisted), not the cause:

SessionStateVersionthinking blocksempty-textwith-text
live, workinghealthy2.1.154990
completed normallyhealthy2.1.152 / 2.1.15381810
completed normallyhealthy2.1.145 / 2.1.1521091090
Session 1broken2.1.15411110
Session 2broken2.1.15412120

Full .jsonl transcripts for both broken sessions exist and can be provided to Anthropic privately (they contain personal data, so they aren't attached to this public issue). I'm also submitting this via /bug from a separate healthy session, which carries the complete unredacted forensic detail and real session IDs.

A separate, unrelated model-reliability issue occurred in the same session (a background sub-agent produced fabricated tool results); it is being reported separately and is not the subject of this issue.

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