Desktop app: multi-agent Workflow run white-screens the app and starves an 8 GB machine; in-flight subagent work is lost
Bug report — Claude Code desktop: multi-agent Workflow run freezes the app (white screen) and starves the machine on 8 GB RAM
Environment
- Claude Code desktop app (Code tab), macOS
Darwin 25.4.0 - Hardware:
Mac15,5— 8 CPU cores, 8 GB RAM (no swap headroom to spare) - Session: single interactive session, no
--print, no cron - Also running (typical dev machine): Chrome, Docker Desktop (started by a subagent for a container-based test), a remote-desktop app
What happened
- I ran the Workflow tool with 6 work items. Each item is a pipeline: 1 implementation subagent → 2 review subagents in parallel → conditional fix + re-review. Worst case ≈ 24 subagents over the run; concurrency is capped by the runtime at
min(16, cpus - 2)= 6 concurrent subagents on this machine. - Subagents do real work:
git worktree add,npm/npx jestsuites (hundreds of tests),tsc --noEmiton a large Next.js app,kubectlreads, and — for one item —docker run nginxfor a container-based verification. - Roughly 10–15 minutes in, the Claude Code window went white and stopped responding. The whole machine became unusable (heavy swapping). I had to force-quit and reopen the app.
- Earlier in the same session, another workflow had completed: 22 subagents, ~4.1 M subagent tokens, 786 tool calls, ~63 minutes. That one survived, but the machine was already under pressure.
Impact
- The background workflow was killed with no completion record; the app reported "no completion record was found … it may have been running when the previous process exited".
- Work from 4 of 6 in-flight subagents was lost. Only the 2 subagents that had already finished (and pushed their branches to git) survived, because
journal.jsonlrecords a result only when an agent completes. Everything an in-flight agent had done (file edits inside its worktree were partially there, but its reasoning/state was gone) had to be redone. - Resume worked (
resumeFromRunId), but re-running the 4 lost agents cost the full token spend again.
Why I think it happens
Concurrency is derived from CPU count only (min(16, cpus - 2)). On a 16-core / 8 GB machine that formula allows up to 14 concurrent subagents; here it allowed 6 — but each subagent can hold a Node/jest/tsc process tree worth several hundred MB, and one was running a Docker container. Free memory dropped to ~60 MB (measured after the crash: Pages free: 3738 × 16 KB). The Electron renderer appears to be a victim of that pressure rather than the cause — it turns white and never recovers.
What would prevent recurrence (in rough priority order)
- Gate subagent concurrency on available memory, not just CPU count. Something like "don't start another subagent while free+inactive memory is under N GB", with N scaled to the machine. A 16-core / 8 GB laptop and a 16-core / 64 GB workstation should not get the same fan-out.
- Expose
maxConcurrency(or a memory budget) as a Workflow tool input, so the caller can self-limit when it knows the subagents are heavy (jest/tsc/docker) rather than token-only. - Checkpoint in-flight subagents, not just completed ones. Writing partial agent state (or at least "started + last tool result") to
journal.jsonlwould make a crash lose minutes instead of a full agent run. - Make the renderer survive memory pressure — or at least fail visibly (an error state you can reload) instead of a permanent white window that requires force-quitting the app.
- Warn at workflow launch on low-memory machines: "this workflow may run up to N concurrent subagents; this machine has 8 GB RAM" is enough for the caller to reduce the plan.
Workaround I applied
Restructured the script to process the work items in waves of 2 (max ~4 concurrent subagents instead of 6) and made every subagent's setup step idempotent, so a resume picks up existing worktrees/branches instead of failing on git worktree add -b.
No confidential project details are included in this report; it is about the harness behaviour only.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗