[BUG] Windows: memory-pressure governor evicts `0 of 0` idle sessions while 15+ are live - app reaches 12.4 GB RSS, stalls, must be force-killed

Status Open
Reported on v2.1.258
Maintainer reply None cached
Activity 1 comment · opened Sep 4, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report
  • [x] I am using the latest version

What's Wrong?

Environment

  • Windows 11 Home Single Language, 10.0.26200.9168
  • Intel i5-12450HX, 16 GB RAM
  • Claude desktop 1.46388.2.0 (MSIX, Claude_pzs8sxrjxfjjc), claude-code backends 2.1.258 / 2.1.260
  • Remote Control connected; typically 10–19 sessions open

Summary

The desktop app has a memory-pressure governor (CliGovernor) that evicts idle sessions when RAM runs low. Across 4 days of logs it fired 44 times and found no eviction candidates on 43 of them — including at critical level with 32 MB of system RAM free — while simultaneously reporting 9–19 live sessions. The process tree then stalls, the UI stops responding, and the app has to be force-killed, which lands the user in the relaunch failure of #92005.

The eviction machinery itself works. The candidate selection is what fails.

Evidence — %LOCALAPPDATA%\Claude\logs\main.log, span 2026-08-31 08:49 → 2026-09-04 08:08, 5,316 [process-memory] samples.

Governor outcomes over that window:

44   [CliGovernor] memory pressure events      (35 warning, 9 critical)
43   "evicted 0 of 0 idle session(s)"          <-- empty candidate pool
 1   "evicted 1 of 11 idle session(s)"         <-- works when it finds candidates

Effective session counts reported at those moments: 9, 11, 13, 14, 15, 17, 18, 19 — never zero.

The critical event, verbatim:

2026-09-03 22:36:33 [warn] [CliGovernor] memory pressure (critical): evicted 0 of 0 idle session(s), 15 effective

System free RAM in the adjacent [process-memory] sample: 32 MB of 16,108 MB.

Leading hypothesis: the idle reaper's veto empties the governor's candidate pool

Five seconds before that critical event, the warm-lifecycle reaper tried to pause every idle session and was vetoed on each one:

22:36:28 [info] [WarmLifecycle:session] Idle timeout reached, disconnecting local_<id>
22:36:28 [info] [CCD] Skipping pause for session local_<id> - remote control is active (startup-policy bridge)

...repeated for every session in turn. Frequency of each veto reason across the log:

587  remote control is active (startup-policy bridge)
 10  1 active background task(s)
  9  2 active background task(s)

active background task(s) is a legitimate veto and is rare. remote control is active (startup-policy bridge) appears to be applied per-session and unconditionally whenever Remote Control is connected — 587 times between 2026-09-03 00:47:10 and 2026-09-04 01:23:43 — which would explain a permanently empty idle pool.

To be precise about what the logs do and don't establish: they establish the empty pool, the veto, and the correlation; they do not establish the causal link inside the code. But the one occasion the governor did see candidates, it behaved correctly and immediately:

23:07:54 [warn] [CliGovernor] memory pressure (warning): evicted 1 of 11 idle session(s), 15 effective
23:07:54 [info] [CliGovernor] pressure evicting local_<id> (idle 481s)
23:07:54 [info] [CCD] Pausing session local_<id> (governor_evict)

So the eviction path is fine. Something is removing sessions from the pool before the governor ever ranks them.

Consequences observed

  • Peak process-tree RSS 12,415 MB on a 16 GB machine (2026-09-01 10:25:43; 185 children; 762 MB free).
  • 97 of 5,316 samples under 1 GB free; 37 under 500 MB; low-water mark 8 MB free (2026-08-31 19:16:00).
  • Peak child process count 239 (2026-09-03 21:36:29).
  • Main-process event loop stalls as memory runs out — 3,222 ms, then 8,088 ms blocks — which is the UI hang users report:

``
22:36:00 [warn] [event-loop-stall] main process blocked for 3222ms (... cumulative 21980ms ...)
22:36:54 [warn] [event-loop-stall] main process blocked for 8088ms (... cumulative 30609ms ...)
``

  • Windows' own resource-exhaustion detector has flagged claude.exe twice, on two different versions: RADAR_PRE_LEAK_64 for 1.24012.9.0 (2026-08-04) and for 1.44121.4.0 (2026-09-03 21:06, ~90 minutes before the critical event above). In fairness this signal is weak on its own — RADAR also fired for Chrome, MATLAB, dwm.exe and OneDrive on this machine over the same period — so I offer it only as corroboration, with the recurrence across two versions being the part worth a look.
  • These episodes are invisible to crash telemetry. No Application Error or AppHang WER event is ever recorded for claude.exe, because the user force-kills it before Windows declares it hung, and %APPDATA%\Claude\Crashpad\reports\ is empty. That may be why this is under-reported relative to how often users hit it.

What Should Happen?

Under memory pressure — certainly at critical — the governor should be able to evict idle sessions. A critical event that evicts 0 of 0 while 15 sessions are live and 32 MB of RAM remains is the governor failing at precisely the moment it exists for.

Suggested directions:

  1. Make the veto pressure-level-aware. Keeping a session warm for Remote Control responsiveness is reasonable at none/warning; at critical, staying alive matters more than staying warm.
  2. Distinguish "pinned" from "not idle". A session idle for 481 s is an eviction candidate regardless of why it is pinned. Today such sessions appear to be excluded from the pool outright rather than ranked lower.
  3. Log the rejection reasons at pressure time. evicted 0 of 0 cannot distinguish an empty pool from a fully-filtered one. Emitting the filter counts would have turned this investigation into a one-line diagnosis.
  4. Consider a ceiling on child process count and tree RSS relative to physical RAM. 239 children and 12.4 GB on a 16 GB machine leaves nothing for the OS.

Steps to Reproduce

  1. 16 GB Windows 11 machine, Claude desktop, Remote Control connected.
  2. Open ~15 sessions and work across them for several hours.
  3. Watch %LOCALAPPDATA%\Claude\logs\main.log for [CliGovernor] memory pressure.
  4. Observe evicted 0 of 0 idle session(s), N effective with N well above 0, preceded by [CCD] Skipping pause ... remote control is active (startup-policy bridge) for every session.
  5. Continue until [event-loop-stall] reaches multiple seconds. The app becomes unresponsive and must be force-killed — after which relaunch fails per #92005.

Claude Code Version

Desktop 1.46388.2.0; claude-code 2.1.260

Platform

Windows

Additional Information

The failed relaunch after the force-kill is #92005, where I have added the Restart Manager / exclusive-lock mechanism. This issue is about what causes the hang; that one is about what blocks the restart.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗