claude-code - 💡(How to fix) Fix Mid-session model switch corrupts conversation when extended thinking is enabled (API 400: 'thinking blocks cannot be modified')

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…

Switching models mid-session in Claude Code while extended thinking (alwaysThinkingEnabled: true) is on permanently corrupts the conversation. Every subsequent turn fails 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.

Once it triggers, the session is unrecoverable from inside the CLI — typing anything just re-ships the now-mixed-model history and re-fails.

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.

  1. Continue the conversation. After a few turns the next API request 400s with the "thinking blocks cannot be modified" error, and stays broken on every retry.
  2. Warn / block on /model when there are signed thinking blocks in the history. Cheapest fix and prevents the failure mode.

Root Cause

Thinking blocks come back from the API with cryptographic signatures that are model-specific. They have to be returned verbatim on later turns. After a /model switch the persisted history still contains thinking blocks signed by the previous model; once a later turn re-ships one of those, the API refuses because the signature doesn't validate under the currently-selected model. The CLI happily accepts the model switch but doesn't reconcile the history, so the breakage is just delayed by however many turns it takes to re-hit a prior signed block.

RAW_BUFFERClick to expand / collapse

Summary

Switching models mid-session in Claude Code while extended thinking (alwaysThinkingEnabled: true) is on permanently corrupts the conversation. Every subsequent turn fails 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.

Once it triggers, the session is unrecoverable from inside the CLI — typing anything just re-ships the now-mixed-model history and re-fails.

Reproduction

  1. ~/.claude/settings.json: "alwaysThinkingEnabled": true.
  2. Start a claude session on, say, Opus 4.7.
  3. Run a handful of turns including tool calls (so several thinking blocks are produced and persisted).
  4. /model to a different model (e.g., Opus 4.8 — or any other model).
  5. Continue the conversation. After a few turns the next API request 400s with the "thinking blocks cannot be modified" error, and stays broken on every retry.

Why this happens

Thinking blocks come back from the API with cryptographic signatures that are model-specific. They have to be returned verbatim on later turns. After a /model switch the persisted history still contains thinking blocks signed by the previous model; once a later turn re-ships one of those, the API refuses because the signature doesn't validate under the currently-selected model. The CLI happily accepts the model switch but doesn't reconcile the history, so the breakage is just delayed by however many turns it takes to re-hit a prior signed block.

Expected behavior

Any of:

  1. Warn / block on /model when there are signed thinking blocks in the history. Cheapest fix and prevents the failure mode.
  2. Auto-purge prior-model thinking blocks from the persisted history on model switch, with a one-line notice ("prior reasoning context cleared for model switch"). The next turn proceeds without that context but the conversation isn't bricked.
  3. Repair tooling: a /recover or claude session repair <sid> command that truncates the JSONL to the last single-model boundary and lets the user resume. Today this requires hand-editing the JSONL on disk, which is awful UX for a known failure mode.

Actual behavior

The CLI silently allows the switch, then 400s some number of turns later with no path to recover from the prompt. The only fixes are: (a) start a fresh session (lose all context), or (b) manually truncate the session JSONL to before the model switch and --resume on the original model.

Evidence from a real broken session

  • 1053-line session JSONL at ~/.claude/projects/<sanitized-cwd>/<sid>.jsonl.
  • 290 assistant messages signed model: claude-opus-4-7, then 14 signed model: claude-opus-4-8.
  • First 400 hit on messages.113.content.4 shortly after the model switch.
  • Every subsequent input (continue, anything) re-shipped the same mixed history and re-hit the 400 identically. /clear is the only working escape, which throws away the whole conversation.

Environment

  • Claude Code (latest stable as of filing).
  • ~/.claude/settings.json: "alwaysThinkingEnabled": true.
  • macOS, zsh.

Happy to attach a sanitized excerpt of the broken JSONL on request.

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…

FAQ

Expected behavior

Any of:

  1. Warn / block on /model when there are signed thinking blocks in the history. Cheapest fix and prevents the failure mode.
  2. Auto-purge prior-model thinking blocks from the persisted history on model switch, with a one-line notice ("prior reasoning context cleared for model switch"). The next turn proceeds without that context but the conversation isn't bricked.
  3. Repair tooling: a /recover or claude session repair <sid> command that truncates the JSONL to the last single-model boundary and lets the user resume. Today this requires hand-editing the JSONL on disk, which is awful UX for a known failure mode.

Still need to ship something?

×6

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

Back to top recommendations

TRENDING