Session permanently broken with 400 'unexpected end of data' after binary tool output (real-world case of #94055)
Summary
A long-running Claude Code session (CLI, v2.1.270/271) becomes permanently broken with repeated 400 errors:
API Error: 400 The request body is not valid JSON: unexpected end of data: line 1 column N (char N-1)
The session never recovers — every subsequent turn, including fork sub-agents, hits the same error. Restarting Claude Code and resuming the session recovers temporarily, but the error recurs as the session continues.
This is likely the same root cause as #94055 (NUL bytes in Bash tool output causing JSON body truncation). The session involved processing binary ciphertext data, and some Bash tool results likely contained NUL or non-UTF-8 bytes that poisoned the conversation history.
Relationship to #94055
This issue provides additional real-world signal on the same underlying bug:
- Real-world trigger: Binary data processed by CLI tools (not a synthetic repro)
- Persistence across restarts: The error recurs when resuming the session after restarting Claude Code, because the poisoned tool result is replayed from the session transcript
- Escalating truncation positions: The column position increases over time as more content accumulates, suggesting the truncation tracks the position of the bad bytes
- Sub-agent propagation: Fork sub-agents inherit the poisoned context and also fail
- Not a context-size issue: Session was at ~58% context utilization when errors began
Error Details
- Total occurrences: 30 error entries in the session transcript across 3 distinct time clusters
- Truncation column positions (chars, sorted):
- Cluster 1 (~19:19-19:21 UTC): 1,033,239 → 1,033,372 → 1,034,660 → 1,037,925 → 1,038,214 → 1,038,361 → 1,039,533 → 1,039,680
- Cluster 2 (~21:37 UTC): 1,540,449
- Cluster 3 (~22:38-23:28 UTC): 1,647,727 → 1,647,995 → 1,723,655
- Pattern: Column positions increase between clusters (session grew between restarts), but vary slightly within a cluster (different tool call overhead per request)
Sample Request IDs
req_011Cf3sahuzbPYZF1biu3qvj
req_011Cf3sajSX3ik9VUjQGLyJB
req_011Cf3scU957xDJRoqyBWc3K
req_011Cf446NM1cYbpXGNrRdppy
req_011Cf48iDsFFUqhwHSQ4JUFW
req_011Cf4CZXLgprhoMbUwogUqA
Environment
- Claude Code version: 2.1.270 (upgraded to 2.1.271 mid-session)
- OS: macOS Darwin 25.6.0
- Model: claude-opus-4-6 (1M context)
- Session duration: 7+ hours before first error
- Context utilization at error onset: ~58%
- Sub-agents spawned: 30+, including forks
Expected Behavior
Claude Code should either:
- Sanitize tool output to remove NUL/non-UTF-8 bytes before adding to conversation history
- Detect the serialization failure before sending and provide a clear error with recovery options (e.g., auto-compact to drop the poisoned message)
- Not replay poisoned tool results from the session transcript on restart
Additional Notes
- The session involved Bash commands that processed binary ciphertext data — standard CLI workflows that can produce binary output
autoCompactEnabledwas set tofalse, so the poisoned content was never automatically compacted away- Even with auto-compact enabled, the issue would likely persist since the poisoned message stays in the transcript
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗