[BUG][Windows] Session restore fires a burst of concurrent taskkill /T that exhausts the WMI per-user quota (still in 2.1.295)
Summary
When Claude Desktop restores or re-spawns many Code sessions at once on Windows, a burst of taskkill.exe /PID <pid> /T /F processes runs concurrently. taskkill /T builds the process tree with a full WMI Win32_Process enumeration, so the burst turns into dozens of concurrent full enumerations. On this machine at least 94 of them failed within 10 seconds. Successful WMI calls are not logged, so the real number of calls is higher.
WMI's per-user arbitrator allows only 30 outstanding tasks per user (OutstandingTasksPerUser = 30, the default). The excess calls are cancelled (0x80041032), and while the quota is exhausted every WMI client running as the same user fails with "Call cancelled" or "Quota violation", including Claude Code's own Get-CimInstance probes.
This is the same taskkill /T → WMI amplification as #73785, #67888 and #79467 (all auto-closed as inactive, not fixed), with a different trigger (a session-restore burst instead of statusline cancellation or a runaway loop) and with the specific limit that is hit. It is still present in 2.1.295.
Environment
- Windows 11 Home 10.0.26200 (x64)
- Claude Code 2.1.295 (native
claude.exe, spawned by Claude Desktop) - Claude Desktop 2.31226.1.0 (MSIX)
- 18 concurrent Code sessions with several stdio MCP servers each, ~1,400 processes on the machine
What happened (2026-10-12, local time)
- 12:02 — Claude Desktop re-spawns the sessions (
main.log:[CCD] session spawn on required_version …,Updated session local_…). - 12:02:21–12:02:31 —
Microsoft-Windows-WMI-Activity/Operationallogs 94 × event 5858 withResultCode 0x80041032for
````
SELECT __PATH, ProcessId, CSName, Caption, SessionId, ThreadCount, WorkingSetSize,
KernelModeTime, UserModeTime, ParentProcessId FROM Win32_Process
each from a different short-lived client PID.
- 12:02–12:23 — the same query failed 155 times from 153 distinct client PIDs (94 at 12:02, 24 at 12:03, 10 at 12:04, 12 at 12:06–12:07, 15 at 12:23).
- None of the client PIDs was a PowerShell process at that time (cross-checked against
Microsoft-Windows-PowerShell/Operationalevent 40961; 23 PID matches were reuse, more than 30 s apart).
Why it is taskkill /T
- The field list above matches the UTF-16 strings in
C:\Windows\System32\taskkill.exe, includingParentProcessId, which/Tneeds.tasklist.exehas noParentProcessIdstring, andwmic.exeis not installed. - The 2.1.295 binary contains
killProcessTree→taskkill.exe /PID <pid> /T /F. The Desktop app bundle (app.asar) referencestaskkill.exein 7 places, one of them next to[CCD-SessionRecovery]. - Not proven: which process launched these
taskkillcalls, the CLI'skillProcessTreeor the Desktop app's session recovery. Both contain the call. The client processes had exited before they could be attributed, and the WMI trace log was not enabled. Killing each session's stdio MCP server trees onetaskkill /Tat a time is the most likely source, but this is a hypothesis.
Which limit is hit
root:__ArbitratorConfiguration (defaults, never changed on this machine):
| Setting | Value |
|---|---|
| OutstandingTasksPerUser | 30 |
| OutstandingTasksTotal | 3000 |
| TaskThreadsPerUser | 3 |
| TotalCacheMemoryPerUser | 2048 KB |
The provider host was not the bottleneck. During a later quota episode (12:23–12:24, when Get-CimInstance Win32_Process returned "Call cancelled" and Get-WmiObject Win32_Process returned "Quota violation" for at least ~35 s), the CIMWin32 WmiPrvSE.exe used 17 MB and 291 handles, against __ProviderHostQuotaConfiguration limits of 512 MB and 4096 handles. With ~1,400 processes, each full Win32_Process enumeration is slow, so each taskkill /T holds one of the 30 per-user slots for a long time.
Impact
- During the burst every WMI consumer running as the same user fails: Claude Code's own PowerShell
Get-CimInstance Win32_Processprobes (ancestors, children, creation time), the Desktop app'sGet-CimInstance Win32_ComputerSystem, monitoring scripts. - The cost grows as sessions × servers × processes: more open sessions mean more processes for each enumeration to walk and more enumerations running at once.
Suggested fix
- Kill the tree without WMI: take one
CreateToolhelp32Snapshot(it includesth32ParentProcessID), compute the descendants andTerminateProcessthem. That is one snapshot per session instead of onetaskkill /Tper child. - Or run each MCP server and Bash child inside a Job Object with
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE(see also #62659) and close the job. - At minimum, serialize the
taskkill /Tcalls within a session and across sessions during a restore.
Steps to reproduce
- On Windows, open Claude Desktop with 15 or more Code sessions, each with several stdio MCP servers.
- Trigger a restore or re-spawn of all sessions (app restart or a CLI version change).
- Run
Get-WinEvent -FilterHashtable @{ LogName='Microsoft-Windows-WMI-Activity/Operational'; Id=5858 }and look for a burst of0x80041032for the query above within a few seconds.
---
Diagnosed by Claude Code (claude-opus-5-5) on the affected machine at the owner's request. All measurements were read-only: event logs, a process snapshot sampler and string scans of the binaries. Body corrected shortly after filing: the first version overstated the burst (it counted a 15-minute window as 2 seconds) and stated the caller as fact.