[BUG] Session becomes permanently unrecoverable after empty text content block during streaming
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
A Claude Code session becomes permanently unrecoverable when the model streams an empty text content block alongside thinking blocks. After the API rejects the malformed response, every subsequent operation fails because the erroneous assistant message remains stuck in the conversation history. The error recovery code does not discard or repair it.
When this happens:
- Retry fails with the same error
- /compact fails (needs API call with corrupted history)
- /debug fails (same reason)
- Session is permanently bricked — only manual JSONL surgery recovers it
What Should Happen?
When the API rejects an assistant message, Claude Code should:
- Discard the malformed assistant message from conversation history
- Allow the user to retry cleanly
- At minimum, /compact should recover by dropping the bad message
Error Messages/Logs
First error (from the empty text block):
messages: text content blocks must be non-empty
All subsequent errors (from re-serialized thinking blocks):
messages.1.content.1: thinking or redacted_thinking blocks in the latest assistant message cannot be modified. The thinking and redacted_thinking fields must contain their original values from the API response.
Error cascade repeats every retry with 85+ failed attempts recorded in transcript.
Steps to Reproduce
- Run a long conversation (~5500 JSONL lines) using Opus 4.6 with extended thinking enabled
- Fill context window until auto-compaction triggers
- Send a message after compaction fires
- Observe that response comes from Haiku instead of Opus (post-compaction model downgrade)
- Response contains empty text content block between two thinking blocks
- API rejects with "text content blocks must be non-empty"
- User attempts retry, /compact, or /debug
- Every operation re-sends corrupted message → cascading "thinking blocks cannot be modified" errors
- Session is permanently unrecoverable — no command can fix it
Non-deterministic streaming issue, but happens reliably under these conditions:
- Extended thinking enabled
- Post-compaction turn (after model downgrade to Haiku)
- Large cached context (~67K tokens)
- Model producing thinking → text → thinking → text → tool_use pattern
Claude Model
Not sure / Multiple models
Is this a regression?
Yes, this worked in a previous version
Last Working Version
2.1.37
Claude Code Version
2.1.38 (Claude Code)
Platform
Anthropic API
Operating System
Ubuntu/Debian Linux
Terminal/Shell
Other
Additional Information
Root Cause: The model (Haiku 4.5 - claude-haiku-4-5-20251001) streamed an empty text content block between two thinking blocks during post-compaction response:
- Content block 0: thinking block (346 words)
- - Content block 1: text block with empty string "" ← the poison
- - - Content block 2: thinking block (156 words)
- - - - Content block 3: text block (actual response)
- - - - - Content block 4: tool_use
The empty text block is invalid when re-sent to the API, but it was the streaming response itself that produced it.
Workaround: Sessions can be manually recovered by:
- Locate the corrupted assistant message (contains empty text block)
- 2. Truncate the JSONL transcript at the last clean assistant turn
- 3. Resume with
claude --continue
This workaround has been validated as working, though it requires manual file editing.
Related Issues: Similar symptoms reported in #23463 (context overflow), #12743 (thinking block API errors), and #10343 (unrecoverable state). This issue is more specific: empty text blocks during streaming at post-compaction, with evidence of model downgrade from Opus → Haiku as a contributing factor.
This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗