Feature/product: Cursor IDE. Related to the closed thread here: Slowness since 2.0 (reopening as a new topic since that one is closed and I have a specific repro).
Quitting Cursor consistently takes ~20-23 seconds, stuck on “Saving UI state.” Logs show the delay is caused by Cursor’s own “slow DB on close” diagnostic routine failing with ENOPRO: No file system provider found, because the disk filesystem provider is already torn down by the time this diagnostic runs during shutdown.
Steps to Reproduce
Open Cursor with a few windows/workspaces.
Quit normally (Cmd+Q or Cursor menu to Quit).
Observe “Saving UI state” hangs for ~20+ seconds.
Check ~/Library/Application Support/Cursor/logs/latest/main.log for ENOPRO errors around the time of quit, e.g.:
[storage main] figuring out stats for slow DB on close() resulted in an error ENOPRO: No file system provider found for resource globalStorage/state.vscdb
CodeExpectedError: ENOPRO: No file system provider found for resource globalStorage/storage.json
at nm.withProvider (main.js:369:3051)
at async nm.withWriteProvider (main.js:369:3423)
at async nm.writeFile (main.js:369:6206)
at async r7.doSave (main.js:59:19185)
Expected Behavior
Quit should complete in a couple seconds like it did before. The “slow DB on close” diagnostic and the final storage.json save should succeed instead of hitting ENOPRO.
Not caused by globalStorage/state.vscdb bloat. I had a separate, legitimate bloat issue (4.4GB db, 441k cursorDiskKV rows from accumulated agent/chat session data) that I fixed by clearing the db; this quit delay persists afterward with a healthy, small (~4MB) db.
Not caused by stale workspaceStorage. Cleared 159 folders untouched 90+ days, no change.
Not specific to any one extension. Tested disabling anysphere.remote-ssh and anysphere.remote-containers (both recently updated, both register their own filesystem providers); the quit time and the ENOPRO class of error were identical with them disabled.
Suspected cause: shutdown-order race where the main process’s disk filesystem provider is disposed before the storage service’s close-diagnostics (“figuring out stats for slow DB on close”) and final storage.json save complete.
Hey @tommulkins, thanks for the detailed report and for ruling out the database size and those extensions.
One note on the logs: the ENOPRO lines are a side effect rather than the cause. That “slow DB on close” check only runs after closing has already taken more than a couple of seconds, and by then the file system layer is already shutting down, so the check itself fails. It doesn’t add to the wait.
To find which step is actually holding up quit, could you try this:
Quit Cursor completely.
Reopen Cursor the way you normally do, with the same windows.
Wait about a minute, then press Cmd+Q and time how long it takes to close.
Before opening Cursor again, go to ~/Library/Application Support/Cursor/logs/ and open the newest folder.
Open main.log and copy every line that contains ShutdownHangWatchdog. Those lines name the step that was slow and how long it took.
Repeat steps 1 to 5, but in step 2 start Cursor from Terminal with: open -a Cursor --args --disable-extensions
Please reply with both sets of lines and the two quit times. It also helps to know roughly how many windows you had open, and whether you use the Agents window or worktrees.
Slow quit (Cmd+Q took 12–16s) — resolved, root cause outside Cursor
Symptom: Cmd+Q took 12–16 seconds on Cursor 3.23.12 (macOS). main.log showed:
[ShutdownHangWatchdog] quit exceeded budget of 8000ms (elapsed=15698ms)
[ShutdownHangWatchdog] will-shutdown joiner ‘applicationStorage’ slow: elapsed=11911ms
[ShutdownHangWatchdog] will-shutdown joiner ‘workspaceStorage’ slow: elapsed=11911ms
Earlier there was also: No ptyHost heartbeat after 6 seconds.
What we found:
Launching with --disable-extensions didn’t help, so it wasn’t an extension.
macOS fseventsd was using 100% CPU (uptime 47 days), which slowed disk writes for every app. Cursor’s save of its storage at quit was stuck behind that.
Several cursor-agent worker and MCP npm exec processes were still running after Cursor quit. One was from an older Cursor version (3.19.13).
Fix: restarting macOS. After that, fseventsd was back to normal and Cursor quit instantly, both with and without extensions.
Possible improvements on Cursor’s side:
The cursor-agent worker and MCP child processes kept running after Cursor quit, including through a version upgrade.
The worker’s API key was passed as a command-line argument (–api-key crsr_…), so any local user could see it with ps. I’ve rotated the key.