Resuming large sessions renders corrupted gibberish in terminal
Bug Description
Resuming a session with claude -r <session-id> renders corrupted gibberish in the terminal. The terminal becomes unrecoverable — Ctrl+C does not work and the only way to exit is closing the terminal tab entirely.
This affects both iTerm2 and the standard macOS Terminal app.
Environment
- Claude Code version: 2.1.81
- OS: macOS 26.2 (Darwin 25.2.0)
- Node.js: v24.1.0
- Terminals tested: iTerm2, macOS Terminal.app
Root Cause (investigated)
The session JSONL file is structurally valid (no parse errors, no binary content, valid UTF-8). The issue is the TUI renderer being overwhelmed during session replay.
The affected session had:
- 856 lines, 1.9MB total in the JSONL file
- 550 progress messages (streaming partial responses) comprising 66% of the file (1.2MB)
- 14 progress messages over 10KB each (up to 34KB)
- 18 subagent (Agent tool) calls with a 2.5MB subfolder of subagent session data
- 4 tool-result files (~960KB total)
- Total data loaded on resume: ~4.5MB
Reproduction
Any session with heavy subagent usage and many progress messages is susceptible. The specific session used 18 Agent tool calls, 25 Bash calls, and accumulated 550 progress entries.
Workaround
Stripping progress and sidechain messages from the JSONL file restores resumability:
python3 -c "
import json, shutil, sys
f = sys.argv[1]; shutil.copy2(f, f+'.backup')
lines = open(f).readlines()
kept = [l for l in lines if not (json.loads(l.strip()).get('type')=='progress' or json.loads(l.strip()).get('isSidechain',False))]
open(f,'w').writelines(kept)
print(f'Stripped {len(lines)-len(kept)} lines')
" ~/.claude/projects/<project>/<session-id>.jsonl
This reduced the file from 913 → 363 lines (1.9MB → 700KB) and the session resumed correctly. All conversation messages (user + assistant) are preserved — only intermediate streaming state is lost.
Note: --print mode (claude -r <id> --print) works fine with the unmodified session, confirming the data is intact and the issue is purely in the TUI rendering path.
Suggested Fix
The resume/replay path should handle large sessions gracefully. Possible approaches:
- Skip rendering progress messages when replaying history (they represent intermediate streaming state, not final content)
- Throttle/batch the replay rendering
- Only render the last N messages in the TUI viewport instead of replaying the full history
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗