Where does the bug appear (feature/product)?
Cursor IDE
Describe the Bug
The renderer accumulates undisposed event listeners during long agent sessions that dispatch many subagents. VS Code’s built-in leak detector fires 732 times with a single identical stack signature, rooted in observable/listener registration during editor text-model creation.
Roughly 3.5 hours into one session the renderer reached 446% CPU and 2921 MB, the window became unresponsive, and it restarted ~10 minutes later. These warnings are logged at [error] level by Cursor’s own logger.
Stack — grouping all 732 warning blocks by their frames yields exactly one group:
at KAv.create (workbench.glass.main.js:53:13900)
at x8e._event [as event] (workbench.glass.main.js:55:2324)
at x8e.onFirstObserverAdded (workbench.glass.main.js:156:33582)
at x8e.addObserver (workbench.glass.main.js:156:15322)
at Object.onWillAddFirstListener (workbench.glass.main.js:53:11657)
at OSs._event [as onDidChange] (workbench.glass.main.js:55:2576)
at new fL (workbench.glass.main.js:224:34913)
at wgc._createInstance (workbench.glass.main.js:21536:1504)
at wgc.createInstance (workbench.glass.main.js:21536:933)
A deeper capture of the same site also shows bjl._createModelData (workbench.glass.main.js:21061:2522) plus React frames from react-dom/esm-client-production.js.
An observable (x8e) registers a listener on OSs.onDidChange via onFirstObserverAdded → onWillAddFirstListener. The listener is never removed when the owning object is disposed, so the emitter’s listener count grows monotonically. The detector only fires above a per-emitter threshold (175 listeners by default), so 732 firings means the count crossed that threshold 732 separate times.
Accumulation over the session (warnings per hour):
18:00 1
19:00 8
20:00 81
21:00 113
22:00 57
23:00 15
[GlassDiffService] Refresh reports missing git repository warnings appear interleaved throughout, which is consistent with the diff-rendering path being the driver.
Resource peak — from Cursor’s own process-monitor telemetry; peak sample window 299.8s / 30 subsamples:
| CPU | Peak memory | Processes | |
|---|---|---|---|
| Total | 523% | 7283 MB | 61 |
| Renderer | 446% (85%) | 2921 MB (40%) | 1 |
| Main process | 40% | 413 MB | 1 |
Subagent-owned (ownerAgentId set) |
17pp (3%) | 2217 MB (30%) | 18 |
The renderer alone accounts for 85% of CPU. The 18 processes actually attributable to subagents (Xcode toolchain, swift-frontend, SWBBuildService) account for 3%. A new renderer window log directory is created ~10 minutes after this window, indicating the window restarted.
Steps to Reproduce
Not reduced to a minimal case. Observed conditions:
- Long-running agent session (3+ hours) in a Swift/Xcode workspace
- Many subagents dispatched (~16), each producing file edits
- Each edit renders a diff in the editor
Leak warnings begin within the first hour and accumulate steadily.
To check your own logs:
grep -rc 'listener LEAK' ~/Library/Application\ Support/Cursor/logs
Resource data is in ~/Library/Application Support/Cursor/process-monitor/*.log (fields: sampleStart, sampleEnd, rows[].sampleCpuTimeMs, rows[].samplePeakMemMb, rows[].ownerAgentId). CPU% per row = sampleCpuTimeMs / (sampleEnd - sampleStart) * 100.
Expected Behavior
Listeners registered in the onFirstObserverAdded → onWillAddFirstListener path should be disposed when the owning instance (fL, created via wgc.createInstance) is disposed.
Renderer CPU and memory should not grow monotonically with the number of diffs rendered over a session.
Operating System
MacOS
Version Information
Cursor 3.18.9 (build 3.18.9)
macOS 26.6.1 (25G76)
Apple M4, 16 GB RAM
Additional Information
Same workload through Cursor CLI on the same machine: ~495 MB RSS idle, ~1180 MB peak, no CPU excursion. cursor-agent has no renderer, and its 16 subagents run in a single Node process. This isolates the cost to the renderer rather than to agent execution.
What this does not prove: the correlation between the leak warnings and the CPU peak comes from a single session, and I have not attached a profiler to confirm that GC over leaked listeners is what consumed the 446%. The leak itself is confirmed independently by the built-in detector; the causal link to the CPU peak is inference from timing.
Suggestion: 732 [error]-level leak warnings in one session is a signal already present in the logs. Surfacing it in CI or telemetry would catch regressions of this class without needing user reports.
Raw renderer.log available on request.
Does this stop you from using Cursor
Yes - Cursor is unusable