fix(io): copy-fallback for atomic writes on cross-device (EXDEV) rename#2696
Merged
Conversation
…evice link Windows encryption-software filter drivers (e.g. 亿赛通/Esafenet) intercept the temp-file -> target rename that the session, branch, config, and desktop .env/title saves use, returning a cross-device link (EXDEV) even within one directory. The save then fails. Add fileutil.ReplaceFile: it renames as before and, only when that fails, copies the temp file's bytes onto the destination (preserving mode) and removes the temp — the path the encryption drivers allow. Route the rename sites through it. The edit/write tools already write in place, so they were never affected.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2694
What
Make atomic file writes survive Windows encryption-software filter drivers (亿赛通/Esafenet and similar), which reject the temp-file → target
renamewith a cross-device link error (EXDEV) even when both paths are in the same directory.Why
The session save, conversation-branch metadata, config save (
reasonix setup//mcp add//thinking), and the desktop.env/ session-title / display saves all write to a sibling temp file and thenos.Renameit onto the destination. On machines with these drivers that rename fails, so the save fails.Note on #2694: the report's
/apply"edit blocks" trace is from the v1 (Node) line — itsEXDEV: ... renamestring andwrite-file-atomictemp names are libuv's. In v2 thewrite_file/edit_file/multi_edittools already write in place (os.WriteFile), so the edit path was never affected. The same failure mode does exist in v2's rename-based atomic saves, which this fixes.How
New
fileutil.ReplaceFile(tmp, dest): renames as before, and only if the rename fails, copies the temp file's bytes onto the destination (re-applying the temp's mode so a0600config temp doesn't widen) and removes the temp — the copy path the drivers permit. The original rename error is surfaced only if the copy fallback also fails, so genuine failures aren't masked. Routed the five rename sites (agent/save.go,agent/branch.go,config/edit.go,desktop/dotenv.go,desktop/sessions.go) through it.codegraph/install.goalso renames, but that's a directory move during install (a different, recursive case) and out of scope here.Tests
internal/fileutilunit tests cover the rename happy path and the copy fallback (full overwrite of a longer destination + temp removal + mode). Runs on all three OS legs including windows-latest. Desktop module builds and its session tests pass.