fix: use graceful-fs to retry transient EPERM/EACCES/EBUSY on Windows rename#228
Conversation
graceful-fs patches fs.rename on Windows with exponential backoff for EACCES/EPERM/EBUSY, fixing failures caused by antivirus or indexer file locks during concurrent writes. Fixes npm#227
892db2d to
d150f7c
Compare
|
@owlstronaut any thoughts on this to ultimately fix npm/cli#9021? |
|
npm already fully patches This also patches This was specifically to not have to worry about this in our subdependencies (and avoid problems like the one that cause us to remove it in 3.0.0). If things are not working as expected now then this PR shouldn't help either. |
So, after the latest changes in npm/cli#9028, we no longer need this specifically for npm, right? |
Yeah, reading your latest comment in there I think so. This PR doesn't need to exist. |
Summary
On Windows,
fs.renamefails withEPERM: operation not permittedwhen another process (Windows Defender, Windows Search indexer, or a concurrent Node.js worker) holds a transient lock on the target file. This is especially prominent with npm'sinstall-strategy=linked, where many files are written in parallel under a single.store/directory, increasing the window for antivirus lock conflicts.The root cause is that
write-file-atomicuses barerequire('fs'), which has no retry logic.graceful-fsalready patchesfs.renameon Windows with exponential backoff (up to 60s) for EACCES/EPERM/EBUSY errors (polyfills.js#L96-L120).This PR switches from
require('fs')torequire('graceful-fs')to get that retry behavior.Background
graceful-fswas originally a dependency ofwrite-file-atomicbut was removed in v3.0.0 to break a circular dependency that interfered withgraceful-fs's own test suite (isaacs/node-graceful-fs#163). That circular dependency no longer exists sincetapno longer depends onwrite-file-atomic.Changes
require('fs')torequire('graceful-fs')graceful-fs(^4.2.11) as a dependencyt.mock()calls to mock'graceful-fs'instead of'fs'Related issues
npm installon Windows with npm 10.xReferences
Fixes #227, #28