[BUG] Desktop Code tab: /stats scan materializes entire multi-GB transcripts (incl. subagents/) → browser-process V8 heap OOM kills app; CLI handles same sessions fine

Resolved 💬 3 comments Opened Jun 11, 2026 by JPBarringer Closed Jun 22, 2026

Preflight

  • Searched existing issues: the symptom is reported in #48261 (labeled invalid) and its closed duplicates (#55897, #49023), but no issue identifies this specific defect. This report isolates one concrete, code-level bug; it is intentionally narrower than #48261, whose thread demonstrably mixes at least two unrelated crashes (a commenter there confirmed a Windows variant that OOM-classifies at only ~442 MB working set — not heap exhaustion). Please don't dedup-close this into that thread.
  • Single bug report: yes.
  • Latest version: Claude Desktop 1.11847.5, bundled Claude Code SDK 2.1.170.

What's Wrong?

The Code tab's /stats transcript scan materializes every transcript file in full as parsed JS objects. The reader (a3r in the v1.11847.5 bundle) streams lines via readline but pushes every parsed entry into a single array before returning; the consumer then immediately filters to type === "user" || "assistant" and folds into small aggregates. For multi-GB transcripts (mine: one 2.4 GB / 366k-line main transcript plus ~3.5 GB of subagents/agent-*.jsonl from heavy subagent use), the parsed representation exceeds the ~4 GB V8 heap ceiling and the browser process aborts, killing the entire app — V8 heap OOM is not a catchable exception, so the scan's per-file try/catch cannot help. Files are also parsed in parallel batches, so peak memory is a whole batch, not one file.

Aggravating factors:

  • The scan reruns over all transcripts (~970 files here) on every Code-tab initialization.
  • The session-hydration path has a size mitigation (transcript is N bytes; tail-loading last 50 MB) — the stats scan has none.
  • Setting isArchived: true in the session store does not help; the scan walks ~/.claude/projects directly.
  • Because transcripts live in ~/.claude/projects, full app reinstalls (deleting ~/Library/Application Support/Claude) do not fix it — explaining several "reinstall didn't help" reports in #48261.
  • The CLI handles these exact sessions fine; only the desktop materializes full histories.

What Should Happen?

The scan should aggregate in O(1) memory per file. It already has map-reduce structure (parallel per-file parse → fold into date sets / counts / token sums); the reduce is just deferred until after full materialization. Moving the fold inside the existing readline loop — parse a line, keep only user/assistant entries projected to the few fields the stats read, accumulate, discard — yields identical output with no architectural change, since per-file accumulators already merge across the batch. Complementary hardening: cache per-file aggregates keyed on (path, size, mtime) so rescans touch only changed files, and/or extend the existing 50 MB tail-load cap to this path (with a log line, as hydration already does).

Error Messages/Logs

main.log immediately before every crash:

[warn] [CCD] Session f3ecf980-… transcript is 2572486670 bytes; tail-loading last 50 MB
[info] [CCD] /stats scanning 968/992 transcript files since 2026-03-09

Crashpad dump (browser process):

electron.v8-oom.is_heap_oom
electron.v8-oom.location = CALL_AND_RETRY_LAST
… Scavenge 3710.3 (3758.6) -> 3683.5 (3752.5) MB … allocation failure;

Steps to Reproduce

  1. Have a Claude Code CLI session whose transcript in ~/.claude/projects/<project>/ is multi-GB (long-running session with many subagents reproduces fastest; the subagents/ directory counts too).
  2. Launch Claude Desktop → app is stable on Chat/Cowork tabs.
  3. Open the Code tab → crash 5–15 s later. Switching to another tab after the Code tab has initialized does not prevent the crash (background scan).
  4. Workaround that confirms the cause: rename the oversized files so they no longer match the *.jsonl discovery filter (mv <session>.jsonl{,.bak}; mv <session>/subagents{,.bak}) → crash gone. Rename back → crash returns. Fully reversible.

Environment

  • Claude Desktop 1.11847.5 (bundled CC SDK 2.1.170), macOS 26.5.1 (Darwin 25.5.0), Apple Silicon
  • Model: Opus 4.8 (not model-dependent)
  • Regression: unknown — likely present since the stats scan shipped; triggers only once a transcript grows large enough.

Related

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗