fix(web): roll back file editor when save fails - #8424
Conversation
The editor showed new text before the disk write finished. A failed write left that text on screen and kept the file marked unsaved. Reload then showed the old file. On a failed save of the latest edit, restore the last confirmed text, clear the unsaved mark, and toast.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
There was a problem hiding this comment.
UI consistency review found three issues in the new file-save rollback path. The main one is that an interrupted write is now treated as a failed write, which makes the editor discard the user's text and surface a save error — every other command result handler in apps/web filters interrupted results out first.
Posted via Macroscope — UI Consistency
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — This is a focused fix to restore the last confirmed file contents after autosave failures, with guarded handling for concurrent edits and interrupted writes. Production changes are confined to the file editor flow and are accompanied by targeted coordinator tests. You can add or adjust custom eligibility rules. Learn more. |
A failed save rolled the overlay back even when the write was interrupted, the coordinator was unmounted, or a newer edit already sat in the shared cache. Dispose could then write the discarded text. Skip interrupt and unmount. Clear the overlay only if it still matches the failed write. Use a later idle refresh as the confirmed baseline. Toast the write error.
There was a problem hiding this comment.
One finding: the rollback toast calls squashAtomCommandFailure on an un-narrowed AtomCommandResult, which does not typecheck. Details inline.
Posted via Macroscope — UI Consistency
A write that failed after dispose left the next surface showing the optimistic text and still marked unsaved. Rollback now still runs. If a newer overlay is already there, keep that text and mark the file pending again.
There was a problem hiding this comment.
One finding on the new after-dispose rollback path: the coordinator's unconditional onPendingChange(false) cancels the "mark pending again" branch that onRollback uses when a newer overlay is present, so the file tab loses its unsaved indicator while unsaved text is still on screen.
Posted via Macroscope — UI Consistency
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit dc19c82. Configure here.
The coordinator was clearing pending right after onRollback, which wiped the unsaved mark when a newer overlay was kept. Rollback now sets pending itself. Failed saves restore the last confirmed text in the overlay, then confirm it, so a stale readFile does not flash the pre-save file. The toast only squashes Failure results.
A successful save left latestRevision set, so idle query refreshes never updated lastConfirmedContents. A later failed edit then rolled back to the old local save instead of the file now on disk. Reset latestRevision after a successful latest write.

What Changed
The file editor now restores the last confirmed text when a save fails.
Edits still apply to the overlay first. If the latest write fails, the overlay goes back, the unsaved mark clears, and a toast says the save failed. A newer edit that landed during that write is not rolled back. The coordinator retries it.
Why
A failed write left the new text on screen. Reload then showed the old disk contents. Easy to think the file was saved.
UI Changes
Failed saves now toast and restore the last confirmed file text. No other visual change.
Checklist
Note
Medium Risk
Changes autosave and optimistic file cache behavior on write failure; incorrect rollback could drop user edits or show stale disk content, though guards exist for newer overlay edits and interrupted commands.
Overview
Failed file writes no longer leave optimistic editor text on screen.
FileSaveCoordinatornow trackslastConfirmedContents(frominitialContentsand successful saves), exposessyncConfirmedso idle server refreshes update the rollback baseline, and on a non-interrupted persist failure resets internal state and invokesonRollbackinstead of leaving the file “saved.” Interrupted writes and in-flight newer edits are unchanged: stale failures do not roll back newer typing, and overlapping saves still debounce to the latest revision.FilePreviewPanelwires this up by passing loadedcontents, syncing confirmed text whencontentschanges without rebuilding the coordinator on every keystroke, and implementingonRollbackto restore project file query data, clear pending when appropriate, skip rollback if the overlay already diverged, and show a “Could not save file” error toast.Tests cover rollback, baseline refresh, interrupted/dispose edge cases, and concurrent edit behavior.
Reviewed by Cursor Bugbot for commit de49ca5. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Roll back file editor to last confirmed contents on save failure
FileSaveCoordinatornow tracks alastConfirmedContentsbaseline, seeded from a newinitialContentsoption and updated on successful saves and idle external refreshes viasyncConfirmed.latestContentsto the baseline, resetslatestRevisionto 0, and invokes a newonRollbackcallback withfailedContents,confirmedContents, and the persistresult; pending state is intentionally left uncleared so the UI can mark the file as pending.isAtomCommandInterruptedare treated as a distinct case — no rollback, no pending change.useFileSaveCoordinatorwiresinitialContentsand a newuseEffectthat callscoordinator.syncConfirmed(contents)on external content changes, and implementsonRollbackto reset query data and show an error toast.Macroscope summarized de49ca5.