Cursor "Apply" Silently Failed

You hit Apply, Cursor says it's done, but the file never changed — usually a stale snapshot, an outside edit, or a locked file.

You hit Apply in Composer or chat, the button turns green, Cursor flashes “Applied” — and the file in your editor is unchanged. Or it changes for a split second and reverts. This is almost never the model’s fault; it’s the Apply step trying to stitch the diff onto a file whose state no longer matches the snapshot Cursor took. When the base doesn’t match, Cursor bails silently rather than risk a bad write.

First narrow down whether Cursor’s diff engine refused, or whether the OS refused the write.

Common causes

In rough frequency order.

1. Base snapshot is stale compared to disk

Composer took a snapshot of the file when it generated the diff. If you saved, hand-edited in another editor, or ran git checkout between then and Apply, the base no longer matches and the apply gets dropped.

How to judge: open View → Output → Cursor right after the failed apply. Look for apply: snapshot mismatch or base does not match current.

2. Target file is outside workspace or excluded by .cursorignore

If the path Cursor proposes is absolute or points outside the workspace (e.g. ~/.config/...), Apply won’t write by default. Files matched by .cursorignore can be read into context but typically aren’t written back.

How to judge: paste the model’s path into Cmd+P; if it can’t open it or says “file not in workspace,” that’s the cause.

3. File is read-only, unwritable, or locked by another process

Common: files under node_modules, files created by sudo on Linux, files locked by another editor on Windows, project.pbxproj held open by Xcode on macOS.

How to judge: in a terminal run ls -l <file>. If the current user has no write bit, that’s it. On Windows, use handle.exe or Resource Monitor to find the lock holder.

4. Composer chose full-file rewrite, not a focused diff

When the model picks “rewrite the whole file,” Apply has to do a full replace. If your file is >2000 lines or has edits the model didn’t see, Cursor’s merge logic decides the conflict is too big and quietly bails.

How to judge: click “View Diff” on that Composer message. If it’s entirely red + green top to bottom, it’s a full rewrite.

5. Unsaved buffer overwrites the apply

The file tab shows a dot (unsaved). Disk version and editor buffer have diverged. Apply writes to disk, then the dirty buffer flushes back and “reverts” the change.

How to judge: look at the tab before apply. Dot = save first.

6. Extension host hung or crashed

Apply runs through the extension host process. If Output → Extension Host shows Extension host terminated unexpectedly, silent Apply failure is guaranteed.

How to judge: Cmd+Shift+P → “Developer: Show Running Extensions” — Cursor’s own extension entries showing red is the tell.

Before you start

  • Identify which entry point fails: chat, Composer, or Cmd+K. They follow different apply paths.
  • Commit or branch before reproducing so you don’t lose unsaved work.
  • Note your Cursor version (Cursor → About) and active model (bottom-right dropdown). Same prompt behaves very differently across models.

Info to collect

  • Cursor version, OS, active model (e.g. claude-sonnet-4, gpt-5), and whether you’re on Cursor’s proxy or BYOK.
  • Repo size (files, LOC), whether .cursorignore exists, last full index timestamp.
  • Full repro: which files were selected, Cmd+K vs Composer, full prompt text, screenshot of the error or no-op.
  • Last 100 lines of View → Output → Cursor.

Shortest fix path

Ordered by ROI. The first three solve ~80% of cases.

Step 1: Save, then apply

Boring but highest hit rate. Cmd+S the target file, then immediately click Apply. For multi-file edits, Cmd+K Cmd+S to save all.

Step 2: Shrink the diff scope

If Composer wants to change 5 files / 300 lines, go back to chat and ask it to “only modify file X” or “only emit a diff for function foo.” Small diffs apply far more reliably.

Prompt rewrite example:
Before: refactor the whole auth module
After:  only edit src/auth/login.ts, function handleLogin; leave other files alone

Step 3: Check writability and workspace membership

# macOS / Linux
ls -l path/to/file
chmod u+w path/to/file        # grant write to current user

# Verify the file is inside the workspace
realpath path/to/file
# must be a subpath of the open workspace root

If the path is outside the workspace, copy it in, apply, and move it back; or use Cmd+K inline edit instead of Composer.

Step 4: Audit .cursorignore

Open the repo’s .cursorignore. Check whether the target file is matched:

# rules that commonly catch you out
*.generated.ts
src/legacy/**

Comment out the offending rule, reload Cursor so it re-reads ignore, and retry the apply.

Step 5: Fallback — paste from chat

In chat, ask output only the final file content as a single code block. Copy it, switch to the file, Cmd+A, paste, Cmd+S. Always works; you lose the auto-merge.

Step 6: Reload the extension host

Cmd+Shift+P → “Developer: Reload Window” (faster than quitting Cursor). If that doesn’t fix it, “Developer: Restart Extension Host.” Still broken? Roll back: Cursor → Settings → “Switch to previous version.”

How to verify the fix

  • Restart Cursor and reproduce once more so you confirm it’s not a transient session state.
  • Try the same flow in a different repo or on a different machine to separate Cursor config from project state.
  • Have a teammate open the same repo and retry; confirms it isn’t just your local cache.

If it still fails

  • Reduce repro to the minimum: one file, one prompt, no extra context.
  • Roll back the most recent Cursor upgrade / settings.json / .cursorrules change and check whether the issue disappears.
  • Search forum.cursor.com and the Cursor Discord for the exact error string; include version + model + prompt.
  • Grab View → Output → Cursor logs and post to the Bug Reports channel.

Prevention

  • Always Cmd+S before Apply so disk == buffer.
  • Don’t edit the same file outside Cursor while Composer is open (especially: no dual-running Vim/VS Code).
  • Split large refactors into multiple prompts, keeping each diff to one or two files.
  • Commit before any big apply so a failed/wrong apply is cheap to undo.
  • Comment your .cursorignore so it’s obvious which rules will block write-back.

Tags: #Troubleshooting #Cursor #Debug #Apply failed