Cursor renderer keeps crashing

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

Subject: Renderer crashes (“clean-exit”) caused by unbounded growth of state.vscdb — 97% of agentKv blobs are unreachable garbage

Environment

  • Cursor 3.19.7-1788393004 (.deb), installed 2026-09-04
  • Ubuntu 26.04.1 LTS, kernel 7.0.0-31-generic
  • GNOME on Wayland, 30 GB RAM, 79 GB free disk

Symptom

Windows die repeatedly with the dialog:

The window terminated unexpectedly (reason: 'clean-exit', code: '0')

On 2026-09-10 this happened 8 times between 09:58 and 10:09, versus roughly
once a day in the preceding days. Reopening the window works, then it dies again.

From main.log, the pattern before each death is always the same:

[warning] [RendererPing] window 2 (pid 0) blocked for ~17614ms
[error] CodeWindow: renderer process gone (reason: clean-exit, code: <unknown>)

and once, a genuine crash rather than a clean exit:

[error] CodeWindow: renderer process gone (reason: crashed, code: 7)

At the time of the crashes a single renderer process was resident at 1.1 GB.
There was no system memory pressure: 15 GB were available and the kernel OOM
killer never fired. This is the renderer’s own heap, not the machine.

Root cause I was able to identify

~/.config/Cursor/User/globalStorage/state.vscdb has grown to 1.1 GB.
It was 220 MB on 2026-08-27, so it roughly quintupled in two weeks.

Breakdown of the cursorDiskKV table (112,850 rows, 992 MB):

Key prefix Rows Size
agentKv:blob 46,389 472 MB
bubbleId 62,921 433 MB
checkpointId 446 37 MB
composer 1,901 29 MB
composerData 84 12 MB

The important finding is in agentKv:blob:<sha256>. I walked the reference
graph: I collected every 64-hex string appearing in all other rows
(bubbleId, composerData, checkpointId, composer, ItemTable,
composerHeaders), then followed blob-to-blob references transitively.

Result, with all conversations retained and nothing deleted:

  • 1,398 blobs reachable (19 MB)
  • 44,991 blobs unreachable (453 MB)

So 97% of the agent blob store is garbage that nothing references any more.
There appears to be no garbage collection for this content-addressed store:
blobs are written and never reclaimed, even when the conversation that
produced them is gone. This is what is driving the database growth, and the
database size is in turn what stalls the renderer for 15 to 17 seconds and
eventually kills it.

For reference, only 84 conversations exist in total, of which 24 are older
than 30 days. Deleting those 24 old conversations reclaims just 48 MB.
Reclaiming the orphaned blobs reclaims 453 MB. The problem is the blob leak,
not the chat volume.

After removing the orphaned blobs and running VACUUM on a copy, the database
went from 1,109 MB to 565 MB and PRAGMA integrity_check returned ok.

Second, unrelated bug: agent sandbox never starts on Ubuntu

Every extension host start logs this:

ERROR [sandboxPreflight] Preflight failed: Command failed:
/usr/share/cursor/resources/app/resources/helpers/cursorsandbox
--policy ... --preflight-only -- /bin/true
Error: Failed to resolve Linux sandbox backend: Landlock error: Step 1-2/7
(user namespace) failed: Failed to unshare namespaces: EPERM.
Bubblewrap error: Bubblewrap namespace setup failed:
Failed to unshare namespaces: EPERM: Operation not permitted

The cause is Ubuntu’s AppArmor restriction on unprivileged user namespaces,
which is on by default since 24.04:

kernel.apparmor_restrict_unprivileged_userns = 1

Both sandbox backends need unshare() and both are therefore blocked out of
the box on a stock Ubuntu install. Cursor ships no AppArmor profile to allow
this, so the sandbox is permanently unavailable. Either shipping a profile
with the .deb, or detecting this condition and surfacing a clear message
instead of a stack trace, would help.

Third, minor: agent CLI versions are never pruned

globalStorage/anysphere.cursor-agent-worker/agent-cli/.local/share/cursor-agent/versions/
held 11 downloaded versions going back to 2026-07-09, totalling 3.1 GB. Only
the newest is symlinked from bin/cursor-agent. Old versions are never
removed. I deleted nine of them by hand and recovered 2 GB.

What I would ask for

  1. Garbage collection for agentKv:blob, or at least a maintenance command
    that reclaims unreferenced blobs.
  2. Retention or size limits on cursorDiskKV, so the database cannot silently
    reach a gigabyte.
  3. Pruning of old cursor-agent versions after an update.
  4. An AppArmor profile for the sandbox helper on Ubuntu, or a clear diagnostic.

I still have the untouched 1.1 GB database and the full logs, and I am happy
to send them or run any query you need against them.

Steps to Reproduce

detailed in the bug description

Expected Behavior

cursor renderer not crashing would be very nice

Operating System

Linux

Version Information

detailed in the bug description

Does this stop you from using Cursor

Yes - Cursor is unusable

Hey @Maicol_Matteoli, thanks for the detailed write-up. You actually found three separate things, so I’ll go through them one by one.

  1. Crashes clean-exit or code 7. This is a known Linux issue in 3.19.x and it’s not related to your database size. It’s fixed in 3.19.13 and newer, and the current release is 3.19.19. Fully close Cursor and install the latest .deb from Cursor · Download or run sudo apt update && sudo apt install cursor if you installed from the apt repo. Then check Help → About and make sure it says 3.19.19. If you still see renderer process gone after updating, as a temporary fallback you can roll back to 3.18.25 which was stable before this series. Also send the new lines from main.log and we’ll take a look.

  2. Database growth. You’re right that unused agentKv:blob entries aren’t removed automatically right now. We’re tracking this. For now you can free space from inside Cursor without manual SQL.

  • Command Palette Ctrl+Shift+P → Delete Old Chats… if you want to remove older chats. Optional, export anything you need first.
  • Run GC Agent KV Blobs. This removes orphaned blobs and rewrites the database. You’ll need free disk space roughly equal to the current database size, and it can take a couple of minutes.
  • Fully close Cursor via File → Exit so the WAL merges, then check the file size again.
  1. Sandbox on Ubuntu. The .deb installs an AppArmor profile at /etc/apparmor.d/cursor-sandbox, but on AppArmor 4+ Ubuntu 24.04+ you need to enable the userns, line.
sudo sed -i 's/^\s*#userns,/  userns,/' /etc/apparmor.d/cursor-sandbox
sudo apparmor_parser -r /etc/apparmor.d/cursor-sandbox

Then restart Cursor. This is required, but on some Ubuntu 24.04+ setups userns, alone isn’t enough. On AppArmor 4.0 the profile may also need an abi <abi/4.0>, declaration, rules like network unix stream, and network unix dgram, and sometimes signal. If after running the sed and apparmor_parser -r the sandbox still fails at steps 1 to 2 of 7, add the missing rules via a local override so .deb updates won’t overwrite them.

sudo tee /etc/apparmor.d/local/cursor-sandbox >/dev/null <<'EOF'
  network unix stream,
  network unix dgram,
  signal,
EOF
sudo apparmor_parser -r /etc/apparmor.d/cursor-sandbox

Note that the default profile shouldn’t require these manual tweaks. I’ve shared with the team that this should work out of the box on AppArmor 4 and that the docs are not accurate here.

  1. Old cursor-agent versions. Confirmed, older downloads under anysphere.cursor-agent-worker/agent-cli/.../versions/ aren’t cleaned up yet. It’s safe to delete everything except the version that bin/cursor-agent points to, like you did. I’ve shared this with the team.

Start with updating to 3.19.19, that should stop the crashes. Let me know how it goes, especially the sandbox part.

Thanks — here’s the follow-up after 3.19.19.

Crashes. Updating to 3.19.19-1788887598 stopped them. After a full File → Exit and reopen there is no renderer process gone / clean-exit in main.log. RendererPing is enabled and has not hit the 15s block threshold.

Sandbox on Ubuntu 26.04 (AppArmor 5.0.2). The stock profile still does not work out of the box. kernel.apparmor_restrict_unprivileged_userns = 1, and /etc/apparmor.d/cursor-sandbox shipped with #userns, commented in all three profile blocks. There was no #include <local/cursor-sandbox>.

After uncommenting userns, and reloading, preflight still failed at steps 1–2/7 with EPERM. Audit showed:

apparmor="DENIED" operation="capable" profile="cursor_sandbox" comm="newuidmap" capname="dac_override"

unshare -U as a normal user already succeeded; the helper was dying on newuidmap, not on unshare itself. The network unix stream/dgram and signal local rules were not enough.

This local override made preflight succeed (exit 0, and after restart: Preflight … succeeded in 20ms, sandbox supported!):

network unix stream,
network unix dgram,
signal,
capability dac_override,
capability dac_read_search,

plus #include <local/cursor-sandbox> in each profile so the override is actually loaded. Without dac_override, Landlock/Bubblewrap still report “Failed to unshare namespaces: EPERM”, which is a misleading error.

Database / GC Agent KV Blobs. I ran GC Agent KV Blobs (not Delete Old Chats), then File → Exit.

Log:

[GCAgentKvBlobs] GC complete in 36.2s (GC: 32.3s, compact: 3.9s): 48,545 total, 37,174 live, 11,371 deleted

state.vscdb is still 1.2 GB. cursorDiskKV still has ~37k agentKv:blob rows (~349 MB of blob values; the table as a whole is ~1.0 GB).

That does not match the reachability walk I sent earlier, with every conversation kept:

  • 1,398 blobs reachable (19 MB)
  • 44,991 blobs unreachable (453 MB)

The in-app GC is much more conservative: it treated ~37k blobs as live and only deleted 11k. Compaction reclaimed almost no pages (freelist_count ≈ 321). So the leak is still there; the maintenance command does not reclaim the orphaned content-addressed store.

I still have the pre-GC 1.1 GB copy if you want queries against it.

Old cursor-agent versions. Confirmed again after the update: a second tree appeared (2026.09.02-c22c1a3, 524 MB) next to the active 2026.09.08-6caf4ff. I deleted the unused one. bin/cursor-agent still points at the current version.

Excellent follow-up, thanks for the details, especially around the sandbox.

  1. Crashes. Glad 3.19.19 fixed them and renderer process gone and clean-exit are no longer showing up in main.log. That was the Linux-only regression in 3.19.x, unrelated to database size. Consider this closed.

  2. Sandbox on Ubuntu (AppArmor 5.0.2). This is a really valuable find. You’re right that userns, alone isn’t enough, and the actual EPERM isn’t coming from unshare. It’s coming from newuidmap, where the profile denies dac_override, and that bubbles up as the misleading “Failed to unshare namespaces: EPERM”. The working fix via a local override is:

network unix stream,
network unix dgram,
signal,
capability dac_override,
capability dac_read_search,

Plus adding #include <local/cursor-sandbox> in each profile block so the override is actually picked up. I’ve passed the full set to the team, including that the stock profile should pass preflight out of the box on AppArmor 4 and 5, and that the error message is misleading.

  1. Database and GC Agent KV Blobs. You nailed it. The in-app GC is more conservative than your reachability walk. It marked about 37k blobs as live and only deleted 11k, so the orphaned content-addressed store doesn’t get freed and the file stays around 1.2 GB. Compaction returned almost nothing and freelist_count is about 321. This is a known issue we’re tracking. GC treats blobs referenced by orphaned rows as reachable. If your offer still stands, could you please share the 1.1 GB pre-GC copy you saved, either attach it here or send it on request. Also, your reachability-walk log is exactly the signal the team needs.

  2. Old cursor-agent versions. Confirmed. After updating, an unused build shows up next to the active one again. It’s safe to delete everything except the build that bin/cursor-agent points to. I’ve passed this to the team too.

At this point the only open item is the incomplete reclaim in GC. Let me know if you can share the pre-GC database, and I’ll post here once we have an update.

Hi Dean,

sadly cursor has not been able to retrieve the pre GC…must have deleted it when fixing this morning.

@Maicol_Matteoli no worries that the pre-GC copy didn’t get saved. It’s not critical. We already have the main signal: your reachability walk and the GC log itself (48,545 total, 37,174 live, 11,371 deleted). Those show where reclaim is being too conservative and not freeing orphaned blobs. That’s enough for the team to investigate.

Incomplete reclaim in GC Agent KV Blobs is something we’re tracking. I can’t share an exact ETA yet, but I’ll post an update here as soon as I have one.

If the DB starts growing again and you want to help further, please make a copy of state.vscdb before running GC, for example cp state.vscdb state.vscdb.pre-gc, with Cursor fully closed. Then we can compare before and after. But no need to wait for this on purpose.

Everything else is resolved: the crash is gone on 3.19.19, you fixed the sandbox with your local override, and old cursor-agent versions are cleaned up manually. Thanks again for the newuidmap/dac_override find, it’s genuinely valuable.

Well I guess it’s a win win situation, you found a new problem to fix and I solved the crash problem I had.

:slight_smile: