400 'thinking blocks cannot be modified' when a run_in_background tool completes (interleaved thinking + Opus 1M)
Summary
With interleaved (extended) thinking enabled on Opus 4.8 (1M context), the session hard-fails with a 400 the instant an asynchronous tool result is injected back into the conversation — specifically when a run_in_background Bash task completes, and also during the harness's "Invalid tool parameters" error-recovery path. The 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.
This stops the session entirely; the only recovery is rolling back to before the offending turn.
Why this is a harness bug (not user/repo/compaction)
- Reproduces in a fresh session at ~64k of a 1M window — compaction/summarization is not involved (nothing to summarize).
- No hooks configured at user, project, or local scope (ruled out content-mutating hooks).
- The error coordinates
messages.1.content.6indicate the first assistant turn (messages[1]) produced an interleaved layout (thinking -> tool_use -> ... -> thinkingat block 6), and the signedthinkingblock was modified during re-serialization rather than passed back byte-for-byte. - The failure fires exactly when a
run_in_backgroundcommand completes and its result is injected, forcing a re-send of the latest assistant turn. The harness's invalid-tool-params recovery (which rebuilds the assistant message) is the same class of trigger.
Repro
- Opus 4.8 with 1M context + interleaved thinking (default).
- In a fresh session, issue a prompt that makes the model think and then fire a tool with
run_in_background: true(long autonomous skills like/doc-audit,/backlog-sweeptrigger this reliably because they spawn parallel/background tool calls). - When the background task completes, the next API request 400s with the message above.
Observed sequence (from the live session)
Bash(claude update) -> ok (2.1.154 -> 2.1.156)
Bash(sleep 5) -> ok
Bash(claude update; claude --version) -> ok
Bash(claude --version) [run_in_background]
-> Invalid tool parameters (x2)
Bash(kill %1 ...) -> done
Background command "Check installed Claude Code version" completed (exit code 0)
-> API Error: 400 messages.1.content.6: `thinking` ... cannot be modified
The 400 appears on the background-completion injection, not during normal turn-taking.
Impact
- Affects any workflow that combines interleaved thinking with parallel or backgrounded tool calls — i.e. most long-running slash-command skills. Not specific to any one skill.
- Hard stop; lost turn; requires manual rollback.
Environment
- Claude Code: bug reproduced on 2.1.156 (also seen on 2.1.154). Updating to latest did not fix it.
- Model: Opus 4.8, 1M context beta.
- OS: Windows 11 Pro (10.0.26200), shell: Git Bash / PowerShell 7.
- Interleaved thinking: enabled (default).
DISABLE_INTERLEAVED_THINKINGunset.
Likely fix area
The async tool-result injection path (background-task completion + invalid-tool-params recovery) must preserve thinking/redacted_thinking blocks in the latest assistant message verbatim when rebuilding the request, instead of re-encoding/reordering them.
Workaround
Setting DISABLE_INTERLEAVED_THINKING=1 removes the signed interleaved blocks and is expected to avoid the failure mode.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗