MCP server processes leak across sessions, exhausting Windows commit charge (0xC000012D)

Resolved 💬 3 comments Opened Mar 24, 2026 by 2233admin Closed Mar 28, 2026

Bug: MCP server processes leak across sessions, eventually exhausting Windows commit charge

Summary

MCP servers spawned via uv/uvx (and their child python/node processes) are not properly terminated when Claude Code sessions end or reconnect. Over multiple sessions, these orphan processes accumulate until the Windows commit charge limit is exhausted, causing STATUS_COMMITMENT_LIMIT (0xC000012D) errors that make the entire system unable to fork new processes.

Environment

  • Claude Code: 2.1.81
  • OS: Windows 11 Pro 10.0.26200
  • Shell: Git Bash (MSYS2)
  • RAM: 32 GB
  • MCP servers: ~15 globally configured (mix of uv-launched Python servers and node-launched JS servers)

Reproduction

  1. Configure multiple MCP servers (e.g., memU, PageIndex, Memorix, Chrome MCP, Context7, oh-my-claudecode, etc.)
  2. Use Claude Code normally across several sessions (start session, work, exit, start new session)
  3. After ~5-10 session cycles, observe system degradation

Observed behavior

Process snapshot taken when system became unresponsive:

Process          Count    Notes
─────────────────────────────────────────
node             46       MCP server instances (expected: ~10)
python           39       MCP server instances (expected: ~3)
cmd              37       Shell wrappers for MCP launchers
bash             30       Git Bash fork residuals
conhost          26       Console host per shell
uv               18       Python MCP launcher (should exit after spawn)
uvx              18       Python MCP launcher (should exit after spawn)
─────────────────────────────────────────
Total processes  400+     (normal baseline: ~150)

Top memory consumers at time of failure:

 MB  Process
845  claude (instance 1)
698  claude (instance 2)
672  claude (instance 3)
557  bun
485  Obsidian
469  claude (instance 4)
406  VS Code
315  netbird
239  node (largest MCP)
173  python (largest MCP)
165  uv (should have exited!)
159  uv (should have exited!)
152  uv (should have exited!)

Symptoms

  1. bash: fork: retry: Resource temporarily unavailable
  2. dofork: child -1 - forked process died unexpectedly, exit code 0xC000012D (STATUS_COMMITMENT_LIMIT)
  3. Starship prompt git commands timeout
  4. All shell operations fail until manual process cleanup

Root cause analysis

The issue appears to be in MCP server lifecycle management:

  1. uv/uvx launchers don't exit: When used as MCP command, uv run stays alive as a parent process even after the Python MCP server is running. Each session restart spawns a new uv + python pair without killing the old one.
  1. No process tree cleanup on session end: When a Claude Code session ends (user exits, connection drops, or new session starts), the MCP server child processes are not sent SIGTERM/SIGKILL. On Windows, this is especially problematic because there's no process group signaling equivalent to Unix.
  1. cmd.exe + conhost.exe wrapper accumulation: Each MCP server launch on Windows goes through cmd.exe which spawns conhost.exe, adding 2 extra processes per MCP server instance.

Recovery

Manual cleanup via PowerShell restored the system:

# Killed 137 zombie processes:
# - 38 uv/uvx launchers
# - 37 headless cmd shells
# - 38 excess python (kept top 3)
# - 24 excess node (kept top 10)
# Process count: 400+ → 297, fork immediately recovered

Expected behavior

  • MCP server processes should be tracked and terminated when a session ends
  • uv/uvx launcher processes should exit after spawning the MCP server (or be tracked for cleanup)
  • On Windows, the entire process tree (cmd → uv → python) should be terminated together
  • Ideally, a process health check should detect and clean up orphaned MCP processes on session start

Suggested fix

  1. Track MCP process trees: Store PIDs of spawned MCP processes and their children
  2. Session cleanup hook: On session end/restart, terminate tracked process trees (on Windows, use taskkill /T /PID for tree kill)
  3. Startup dedup: On session start, check if an MCP server is already running before spawning a new instance
  4. Health watchdog: Periodic check for orphaned MCP processes (parent PID no longer exists)

Workaround

Users can run this PowerShell one-liner to clean up:

Get-Process -Name uv,uvx -EA 0 | Stop-Process -Force; Get-Process -Name cmd -EA 0 | ? {$_.MainWindowTitle -eq ''} | Stop-Process -Force

View original on GitHub ↗

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