Skip to content

Opening a chat session can silently dirty editor buffers and cause data loss #313703

@hediet

Description

@hediet

Summary

Sometimes when I open a chat session, VS Code silently restores stale agent-edit content into open files, marking them dirty. If the file has been modified since the chat last persisted its state, saving the now-dirtied buffer will overwrite those newer changes — i.e. silent data loss. This happens even for files edited entirely inside VS Code.

Steps to reproduce

  1. In a chat, have the agent edit a file. Call this content S1. Don't Keep/Undo.
  2. Close the chat.
  3. Reload VS Code.
  4. Edit the file (in VS Code) and save it. Call this content S2.
  5. Reload VS Code again.
  6. Open the chat.
  7. The file's editor buffer is replaced with S1 and marked dirty. Saving (or autosave) overwrites S2 on disk with S1 — the user's edits from step 4 are lost.

Root cause

ChatEditingSession.storeState() persists every entry whose state is Modified on shutdown (chatEditingServiceImpl.ts, the onWillSaveState block).

On reopen, _init_initEntries in chatEditingSession.ts restores them:

const restoreToDisk = snapshotEntry.state === ModifiedFileEntryState.Modified;
await entry.restoreFromSnapshot(snapshotEntry, restoreToDisk);

restoreFromSnapshot in chatEditingModifiedDocumentEntry.ts then calls:

await this._textModelChangeService.resetDocumentValues(snapshot.original, snapshot.current);

…which in resetDocumentValues (chatEditingTextModelChangeService.ts) unconditionally rewrites the freshly disk-loaded model with snapshot.current whenever it differs from the current buffer — marking the buffer dirty. There is no check against the actual on-disk content, and no detection that the file changed since the snapshot was taken.

This dirties the buffer (and risks data loss on save) when:

  • The file was edited and saved inside VS Code while the chat was closed.
  • The file was edited outside VS Code, by another tool, or via file sync.
  • EOL / BOM / final-newline differences exist between disk and snapshot → buffer dirtied with semantically identical content.
  • The session was persisted with state === Modified even though the user had moved on.

Expected behavior

Opening a chat session must not silently dirty editor buffers, and must never put a buffer in a state where saving would overwrite newer on-disk content. Restoring pending agent edits should either:

  • be a no-op when on-disk content already matches the snapshot (modulo EOL/BOM),
  • detect that the file changed since the snapshot was taken (mtime/hash) and skip the restore (or prompt),
  • keep only the diff baseline and require the user to explicitly replay/keep/undo, instead of writing back to the modified buffer on session open.

Affected code

  • src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingSession.ts (_initEntries, around the restoreToDisk decision)
  • src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingModifiedDocumentEntry.ts (restoreFromSnapshot)
  • src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingTextModelChangeService.ts (resetDocumentValues)
  • src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingServiceImpl.ts (onWillSaveState persistence)

cc @jrieken @roblourens

Metadata

Metadata

Assignees

Labels

bugIssue identified by VS Code Team member as probable bugpapercut 🩸A particularly annoying issue impacting someone on the team

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions