[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
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: truein the session store does not help; the scan walks~/.claude/projectsdirectly. - 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
- Have a Claude Code CLI session whose transcript in
~/.claude/projects/<project>/is multi-GB (long-running session with many subagents reproduces fastest; thesubagents/directory counts too). - Launch Claude Desktop → app is stable on Chat/Cowork tabs.
- 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).
- Workaround that confirms the cause: rename the oversized files so they no longer match the
*.jsonldiscovery 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
- #48261 — symptom thread (V8 OOM on launch), labeled
invalid, conflates multiple causes. Detailed analysis also posted there: https://github.com/anthropics/claude-code/issues/48261#issuecomment-4682809000
4 Comments
Workaround until this is fixed in the app
If you are experiencing this problem and reading this: track down the large session log (and associated subagent logs) and rename them (add
.bak, for instance) to avoid parsing them during load. Step by step:``
bash
``find ~/.claude/projects -name '*.jsonl' -size +100M -exec ls -lh {} \;
.jsonl:``
bash
``mv "<path-from-step-2>.jsonl" "<path-from-step-2>.jsonl.bak"
.jsonl). If it contains asubagentsfolder, those transcripts are scanned too — rename that folder as well:``
bash
``mv "<project-folder>/<session-id>/subagents" "<project-folder>/<session-id>/subagents.bak"
This will break your ability to use those sessions in an active desktop session (and they won't appear in the CLI's
--resumelist either, since sessions are discovered the same way). But it will restore the desktop app to a usable state, and it is fully reversible once this is fixed — just rename the files back by removing.bak. Nothing is deleted.Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
/statsshould operate over a bounded index, not parsed transcript arrays. Keep per-session counters updated at write or ingest time: message counts, token buckets when present, image/blob bytes, subagent versus main, first/last timestamp, and malformed-line count.The UI path can stream rows and bucket
subagents/separately by default. Regression: a multi-GB transcript tree returns stats without materializing every JSONL entry in browser memory.---
_Generated with ax._
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.