Skip to content

fix: fall back to copy+unlink when rename fails with EXDEV - #241

Open
dyk1454683243-sudo wants to merge 1 commit into
npm:mainfrom
dyk1454683243-sudo:cursor/exdev-rename-fallback-240d
Open

dyk1454683243-sudo wants to merge 1 commit into
npm:mainfrom
dyk1454683243-sudo:cursor/exdev-rename-fallback-240d

Conversation

@dyk1454683243-sudo

@dyk1454683243-sudo dyk1454683243-sudo commented Sep 20, 2026

Copy link
Copy Markdown

Summary

When fs.rename / fs.renameSync fails with EXDEV (cross-device link not permitted), writeFile and writeFileSync now fall back to copyFile + unlink so the write can still succeed.

This is the failure mode in #71: Windows AppX virtualization can make a temp file and destination look like they are in the same directory while the rename is treated as a cross-device move. The same EXDEV also happens on true cross-device dest/tmp pairs (e.g. separate volumes).

Rename remains the default path and stays atomic. The copy fallback is not atomic; that is called out in the README.

Other rename errors (EPERM, ENORENAME, …) still propagate. A failed unlink of the temp file after a successful copy does not fail the write.

Test plan

  • Mocked EXDEV on rename / renameSync with a real filesystem copy (test/exdev.js): dest content is written, temp file is removed, existing dest is replaced
  • Non-EXDEV rename errors still fail and do not copy
  • copyFile failures after EXDEV still propagate
  • Sync write still succeeds if temp unlink fails after a successful copy
  • npx tap on Node 22.22.2: all tests pass, lib/index.js at 100% coverage
  • npm run eslint passes
  • template-oss-check only fails locally on this fork because it wants package.json#repository.url rewritten to the fork; that check is unchanged on npm/write-file-atomic CI

Fixes #71

When fs.rename fails with EXDEV (Windows AppX virtualized paths, or a
true cross-device move), write the temp file with copy+unlink so
writeFile / writeFileSync can still succeed. Rename remains the default
atomic path. Other rename errors are unchanged.

Fixes npm#71

Co-authored-by: David <dyk1454683243-sudo@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

writeFileSync may error with cross-device link not permitted on Windows

2 participants