fix(arborist): retry bin-links on Windows EPERM#9028
Conversation
bff4ae0 to
0d8fa42
Compare
|
We may want to dig into the |
I dug into this. As you already pointed out, npm already calls The reason it doesn't help is that The fix needs to be here at the arborist level. I'll update to use |
…y install On Windows, antivirus and search indexer can transiently lock files, causing write-file-atomic's fs.rename to fail with EPERM during the bin-linking phase. The linked strategy amplifies this by writing many store entries in parallel. Add retry with backoff (up to 5 attempts) for EPERM/EACCES/EBUSY errors in #createBinLinks, Windows only.
0c24d7c to
07a7e5c
Compare
07a7e5c to
b77a47e
Compare
| "version": "9.4.0", | ||
| "license": "ISC", | ||
| "dependencies": { | ||
| "@gar/promise-retry": "^1.0.0", |
There was a problem hiding this comment.
We are making an exception for this PR on our policy accepting dependency updates. This dependency is already in the npm tree, and adding it is only a matter of adding it to the package.json and lockfile. The bundled assets are already present.
There was a problem hiding this comment.
Yes, I already saw it already used in the repo and used the exact same version for the same reason.
|
Oh yes so much cleaner w/ the retry library! |
This contains the changes from - a2154cd (#8996) - 880ecb7 (#9013) - 26fa40e (#9041) - 983742b (#9055) - 10d5302 (#9051) - a29aeee (#9028) - 16fbe13 (#9030) - 8614b2a (#9031) Since Node 22 doesn't have npm 11 yet, it would be better to have this change backported to v10 Also, we wish to use `install-strategy=linked` in the [Gutenberg monorepo](WordPress/gutenberg#75814), which powers the WordPress Block Editor. We are still on v10. So, these fixes will help.
In continuation of our exploration of using
install-strategy=linkedin the Gutenberg monorepo, which powers the WordPress Block Editor, this is a follow up of the fixes from #8996.On Windows,
npm installwithinstall-strategy=linkedfails withEPERM: operation not permittedduring the bin-linking phase. This is hitting us on Windows CI for the Gutenberg monorepo (~200 workspace packages).Summary
During rebuild,
bin-links/fix-bin.jsrewrites hashbang lines in bin files usingwrite-file-atomic, which does a temp-file write followed byfs.rename(). On Windows, antivirus (Windows Defender) and the search indexer can transiently lock files that were just written, causing the rename to fail with EPERM.The linked strategy amplifies this because it writes all packages into
.store/in parallel, increasing the window for antivirus lock conflicts compared to the hoisted layout.Root cause
npm already patches the global
fswithgraceful-fsat startup (entry.js:8), which adds Windows rename retry logic. However,graceful-fs's retry only kicks in when the destination file does not exist — it checksfs.stat(to)after EPERM, and if the target already exists (stat succeeds), it gives up immediately. Inwrite-file-atomic's case, the destination file always exists (it's being overwritten), so the retry never fires.Changes
Wrapped thebinLinks()call inrebuild.js#createBinLinkswith a new#binLinksWithRetrymethod that retries up to 5 times with 500ms–2.5s backoff on Windows when the error code is EPERM, EACCES, or EBUSY.binLinks()call inrebuild.js#createBinLinkswith@gar/promise-retry. On Windows, EPERM/EACCES/EBUSY errors trigger a retry with exponential backoff (5 retries, 500ms min timeout).@gar/promise-retryto arborist's dependencies.process.platform === 'win32'— no behavior change on macOS/Linux.Testing
We tested this approach in our fork and it resolves the issue on Windows CI for the Gutenberg monorepo.
References
Fixes #9021