[Bug] Extended Thinking: Summarized thinking blocks fail signature validation when resent to API
Summary
With extended thinking enabled, a thinking block in the assistant message history intermittently gets modified after it was originally produced. Because the API requires thinking/redacted_thinking blocks to be resent byte-for-byte identical (with their original signature), the next request fails with a 400. Once it happens the conversation is permanently unrecoverable: every subsequent message replays the full history including the corrupted block, so it fails identically every time.
Error
API Error: 400 messages.1.content.6: `thinking` or `redacted_thinking` blocks in the latest
assistant message cannot be modified. These blocks must remain as they were in the original response.
Reproduced in a second, unrelated session with a different index:
API Error: 400 messages.7.content.3: `thinking` or `redacted_thinking` blocks in the latest
assistant message cannot be modified. These blocks must remain as they were in the original response.
Environment
| | |
|---|---|
| Claude Code | 2.1.154 (note: ahead of npm stable 2.1.153 — appears to be a pre-release/nightly build) |
| OS | macOS, Darwin 25.5.0, arm64 |
| Model | Opus 4.8 (1M context) — claude-opus-4-8[1m] |
Relevant settings.json:
"alwaysThinkingEnabled": true,
"showThinkingSummaries": true,
"effortLevel": "xhigh"
Conditions / repro
No crisp deterministic repro yet, but both occurrences shared the same conditions:
- Extended thinking on for every turn (
alwaysThinkingEnabled: true) atxhigheffort, so thinking blocks are present on basically every assistant message. - Long, tool-heavy sequences with many interleaved thinking blocks (one crash followed a ~13-minute background workflow run).
- The second crash occurred immediately after a cancelled parallel
Bashtool call (one of two parallel calls was cancelled), which looks like a likely moment for the assistant message to be reassembled incorrectly.
Key evidence: the thinking-summarizer's prompt leaked into a thinking block
While showThinkingSummaries was on, this fragment appeared inside one of the displayed thinking summaries:
"I need to see the next thinking to rewrite it. Could you provide the next thinking chunk that follows the current rewritten thinking?"
That is not assistant reasoning — it reads like the summarizer/rewriter process's own prompt bleeding into the stored thinking content.
Hypothesized root cause
(Hypothesis, not confirmed.) The thinking-summary feature (showThinkingSummaries) rewrites raw thinking blocks into shorter summaries for display. It looks like the rewritten/summarized content can end up persisted in place of the original signed block, so when that block is resent to the API its content no longer matches the signature → 400 ... blocks cannot be modified. The likelihood seems to rise with the number of thinking blocks in history (high effort, always-on thinking, long workflows) and possibly with tool-call cancellation/reassembly.
Impact
- A single corrupted block bricks the entire conversation — it cannot recover by any further messaging, because the full history (including the bad block) is replayed on every request.
rewindonly helps if the corruption is late in the history; when the bad block is near the start (e.g.messages.1), the whole session is effectively lost.
Workaround
Setting "showThinkingSummaries": false (keeping thinking otherwise enabled) is the suspected fix; falling back to "alwaysThinkingEnabled": false removes thinking blocks entirely so there is nothing to corrupt.
Questions for maintainers
- Does
showThinkingSummarieswrite summarized content back into the message array that is later sent to the API, rather than keeping summaries display-only? - Is there extra risk of thinking-block reassembly corruption when a parallel tool call is cancelled mid-flight?
- Is
2.1.154a known pre-release, and is this a regression vs2.1.153?
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗