fix(arborist): retry bin-links on Windows EPERM#9028
Open
manzoorwanijk wants to merge 1 commit intonpm:latestfrom
Open
fix(arborist): retry bin-links on Windows EPERM#9028manzoorwanijk wants to merge 1 commit intonpm:latestfrom
manzoorwanijk wants to merge 1 commit intonpm:latestfrom
Conversation
9111028 to
bff4ae0
Compare
…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.
bff4ae0 to
0d8fa42
Compare
wraithgar
reviewed
Mar 3, 2026
Comment on lines
+18
to
+20
| // On Windows, antivirus/indexer can transiently lock files, causing | ||
| // EPERM/EACCES/EBUSY on the rename inside write-file-atomic (used by | ||
| // bin-links/fix-bin.js). Retry with backoff for up to ~7.5 seconds. |
Member
There was a problem hiding this comment.
Suggested change
| // On Windows, antivirus/indexer can transiently lock files, causing | |
| // EPERM/EACCES/EBUSY on the rename inside write-file-atomic (used by | |
| // bin-links/fix-bin.js). Retry with backoff for up to ~7.5 seconds. | |
| // On Windows, antivirus/indexer can transiently lock files, causing EPERM/EACCES/EBUSY on the rename inside write-file-atomic (used by bin-links/fix-bin.js). | |
| // Retry with backoff for up to ~7.5 seconds. |
As part of our efforts to increase accessibility we try to keep comments all on one line, breaking only for sentences.
wraithgar
reviewed
Mar 3, 2026
| // EPERM/EACCES/EBUSY on the rename inside write-file-atomic (used by | ||
| // bin-links/fix-bin.js). Retry with backoff for up to ~7.5 seconds. | ||
| /* istanbul ignore next */ | ||
| const retryBinLinks = async (binLinks, node, opts, retries = 4) => { |
Member
There was a problem hiding this comment.
Elsewhere we have delegated retries to a library. There is a LOT that goes into retrying and it's not something we want to hand roll.
wraithgar
reviewed
Mar 3, 2026
Comment on lines
+33
to
+34
| } catch (err) { | ||
| if (retries > 0 && |
Member
There was a problem hiding this comment.
This is a good example of why a retry library is the right option. We can wrap this whole thing in the retry library and then make the decision on whether or not to retry it at all (by checking codes) in our callback.
Member
|
We may want to dig into the |
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.
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
write-file-atomicuses barerequire('fs')and has no retry logic forfs.rename. By contrast,graceful-fsalready patchesfs.renameon Windows with exponential backoff for EACCES/EPERM/EBUSY (up to 60s). Sincewrite-file-atomicdoesn't usegraceful-fs, the rename fails immediately on the first lock conflict.The longer-term fix is for
write-file-atomicto usegraceful-fs(tracked in npm/write-file-atomic#227, with a PR ready - npm/write-file-atomic#228), but in the meantime this PR adds retry logic at the arborist level.Changes
binLinks()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.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