Stale 'Keep all changes' review UI after worktree removal - button is a silent no-op

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

After a git worktree that an agent was working in was removed from disk, an editor tab referencing a file inside that worktree (ledger.py) stayed open. The tab persistently shows a “Keep all changes” review button. Clicking it does absolutely nothing - no diff is applied, no error dialog, no state change. The stale review UI cannot be dismissed.

Steps to Reproduce

  1. Run an agent in a git worktree that creates/edits a file (e.g. ledger.py).
  2. Open that file in an editor tab.
  3. Delete the worktree (e.g. via “git worktree remove”, or delete the folder) without first keeping/discarding the pending changes.
  4. Switch back to the editor tab pointing into the removed worktree.
  5. Observe the persistent “Keep all changes” button and click it.

Expected Behavior

Cursor should either discard the stale review state, show a clear “worktree removed / file no longer exists” notice, or apply the change if still resolvable. Clicking “Keep all changes” should never be a silent no-op.

Operating System

Windows 10/11

Version Information

Version: 3.29.15
Commit: 86776fcb52ca505783155631089b65d646f9b030
Release Track: stable
OS: Windows 10.0.26300 (x64)

Additional Information

Actual Behavior: The “Keep all changes” button is always visible on the tab and clicking it has no effect. The stale review UI persists and cannot be dismissed. Restarting Cursor does not remove the stale tab.

Does this stop you from using Cursor

No - Cursor works, but with this issue

Root cause analysis (found while cleaning up locally)

Update: we dug into the persisted state on our machine. The stale review UI survives window reloads because the pending review state is persisted in the global database:

  • DB: %APPDATA%\Cursor\User\globalStorage\state.vscdb
  • Table: cursorDiskKV
  • Keys: inlineDiff:<workspaceHash>:<diffId> (6 rows in our case, all referencing files under the deleted worktree)

Each row stores a full pending inline diff, e.g.:

{"diffId": "...", "uri": {"external": "file:///d:/workspace/fintech/comein-agent/.worktrees/comein-p3/src/comein_agent/adapters/wss/ledger.py"}, "originalTextLines": ["..."], "persistedAt": 1234567890}

After the worktree directory is deleted from disk:

  1. The diff can no longer be resolved, so clicking “Keep all changes” is a silent no-op (the target file does not exist anymore).
  2. Every window reload / app startup re-creates the review UI from these persisted rows, so the ghost tab always comes back.

Workaround that worked for us: fully quit Cursor, delete the stale rows (DELETE FROM cursorDiskKV WHERE key LIKE 'inlineDiff:<workspaceHash>:%' for the affected workspace), then restart. After that the ghost tab and the dead button are gone for good.

Suggestion for the team: when the file / worktree referenced by a persisted pending inlineDiff row no longer exists on disk, Cursor should drop the stale rows (or surface a cleanup action) instead of re-rendering an unresolvable review UI on every launch. Happy to provide more details if needed.

Hi @dybai, it looks like the button is stuck because Cursor still has a saved pending change for a file inside the removed worktree, and it can’t accept or discard it while that file is missing.

In the meantime, this should clear it:

  1. Recreate the folder at the exact path the worktree used (for example with git worktree add to the same path, or just create the folder by hand).
  2. Put a ledger.py back at the same path the stale tab points to (any content is fine).
  3. In Cursor, click Keep all changes again.
  4. Once the button is gone, you can delete the folder again.

If the button is still there after that, click Review Next File and tell me which file path it opens, since the stale change may belong to a different file from that worktree.

Let me know if that helps!