[BUG] Kernel OOM (not V8 heap) from parallel subagent + per-agent MCP fan-out exhausts host RAM

Open 💬 3 comments Opened Jun 24, 2026 by svashish305

Environment

  • Claude Code on WSL2 (Ubuntu), Windows host
  • Model: Opus
  • Host: ~95 GB RAM; WSL guest capped ~46 GiB, no swap at time of crash

Summary

This is distinct from the V8 heap-exhaustion OOM reported in #16470 and #18011 (both closed/stale).
This is a Linux kernel OOM-killer event: launching several parallel subagents via the
Agent/Task tool spawned a swarm of ~70 node processes whose aggregate RSS (~43.5 GB)
exhausted host RAM. No single process hit a V8 heap limit — each was lean (~620 MB avg). The
kernel OOM-killer fired 3+ times in one boot, killed systemd, and collapsed the WSL distro
(Wsl/Service/E_UNEXPECTED).

What happened

  • Ran a deep multi-repo audit workflow: 6 subagents launched in parallel within ~60 seconds

(single foreground fan-out, no staggering).

  • Each subagent is a full Claude Code process that, while doing real work, **spawns 20+ of its own

tool-use child processes** (Bash/Read across large repos), and every Edit fires PostToolUse lint
hooks (rubocop/eslint = more node). These children compound across all parallel agents.

  • OOM task table (recovered from the persistent journal of the prior boot) showed:

~70 node processes, ~620 MB average, largest 2.7 GB, total ~43.5 GB ≈ 98% of resident memory.

  • OOM-killer fired at roughly 1-minute intervals across the same boot; the session's last activity

was inside that window.

Root cause (hypothesis)

Parallel Agent/Task fan-out appears to have no aggregate memory ceiling and no concurrency cap.
The footprint is driven by tool-spawned children per agent — each subagent runs many concurrent
Bash/Read tool calls (and PostToolUse hooks spawn further node processes), so total resident memory
scales roughly as agents × (tool-children + hook-processes) with no backpressure. (Note: subagents
share the parent session's MCP server set rather than re-spawning it, so MCP duplication is not
the multiplier here — the swarm is tool/hook fan-out across parallel agents.) On a host with a hard
RAM cap (WSL, containers, cgroup limits) this OOM-kills the system rather than degrading gracefully.

Why it's not #16470 / #18011

Those are V8 heap limits inside a single process (FATAL ERROR: Reached heap limit, SIGABRT).
Here every process was well under its heap limit; the kernel killed processes because
physical RAM was exhausted by process count/aggregate RSS, not heap growth in one process.

Suggested mitigations

  1. Cap the number of concurrently-running subagents (or expose a configurable concurrency limit) for

the Agent/Task fan-out path.

  1. Make any such cap memory-aware (aggregate RSS / child-process pressure), not purely count-based

— each agent's tool + hook fan-out, not the agent alone, is the real memory unit.

  1. Surface aggregate child-process memory pressure / warn before the host OOMs.

Repro

  1. In an interactive session, launch 6+ subagents in parallel (multiple Agent calls in one message),

each doing real work that drives concurrent Bash/Read tool calls over large repos (with PostToolUse
lint hooks configured).

  1. Watch total node RSS via ps -eo rss,comm --sort=-rss (or recover the OOM task table from the

persistent journal: journalctl -D /var/log/journal -b -1 | grep -iE 'oom-kill|Killed process|Tasks state').

  1. On a RAM-capped host (WSL/cgroup) the kernel OOM-killer fires before any single process reaches its

V8 heap limit.

View original on GitHub ↗

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