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 andnode-launched JS servers)
Reproduction
- Configure multiple MCP servers (e.g., memU, PageIndex, Memorix, Chrome MCP, Context7, oh-my-claudecode, etc.)
- Use Claude Code normally across several sessions (start session, work, exit, start new session)
- 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
bash: fork: retry: Resource temporarily unavailabledofork: child -1 - forked process died unexpectedly, exit code 0xC000012D(STATUS_COMMITMENT_LIMIT)- Starship prompt git commands timeout
- All shell operations fail until manual process cleanup
Root cause analysis
The issue appears to be in MCP server lifecycle management:
uv/uvxlaunchers don't exit: When used as MCPcommand,uv runstays alive as a parent process even after the Python MCP server is running. Each session restart spawns a newuv+pythonpair without killing the old one.
- 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.
cmd.exe+conhost.exewrapper accumulation: Each MCP server launch on Windows goes throughcmd.exewhich spawnsconhost.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/uvxlauncher 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
- Track MCP process trees: Store PIDs of spawned MCP processes and their children
- Session cleanup hook: On session end/restart, terminate tracked process trees (on Windows, use
taskkill /T /PIDfor tree kill) - Startup dedup: On session start, check if an MCP server is already running before spawning a new instance
- 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 -ForceThis issue has 3 comments on GitHub. Read the full discussion on GitHub ↗