Skip to content

Comments

fix(arborist): skip postinstall on store links in linked strategy#9013

Open
manzoorwanijk wants to merge 2 commits intonpm:latestfrom
manzoorwanijk:fix/linked-strategy-postinstall-double-run
Open

fix(arborist): skip postinstall on store links in linked strategy#9013
manzoorwanijk wants to merge 2 commits intonpm:latestfrom
manzoorwanijk:fix/linked-strategy-postinstall-double-run

Conversation

@manzoorwanijk
Copy link
Contributor

@manzoorwanijk manzoorwanijk commented Feb 23, 2026

Continuing the install-strategy=linked fixes from #8996. While testing on the Gutenberg monorepo, esbuild installs fail because its postinstall script runs twice in parallel against the same store directory.

Summary

With install-strategy=linked, postinstall scripts run twice for every store package — once for the store entry and once for its symlink. For packages like esbuild whose postinstall modifies files in-place (fs.linkSync to replace the JS wrapper with a native binary), this race condition corrupts the install.

Root cause

In rebuild.js, #runScripts destructures isStoreLink from node.target (the store entry) to decide whether to skip a node. But isStoreLink is a property of the link node itself (node), not its target. Store entries don't have isStoreLink, so it's always undefined and the guard never triggers. Both the store entry and the store link run scripts against the same directory in parallel.

Changes

  • Fixed the skip condition in rebuild.js #runScripts to use node.isLink && node.target?.isInStore instead of reading isStoreLink from node.target. This correctly skips store links (symlinks pointing to store entries) while still allowing workspace links and store entries themselves to run scripts.
  • Added a regression test that verifies postinstall scripts run exactly once for store packages.

References

Fixes #9012

…tegy The isStoreLink guard in rebuild.js was reading from node.target (the store entry) instead of node (the link), so it was always undefined. Both the store entry and its symlink ran scripts against the same directory in parallel, causing race conditions in packages like esbuild. Check node.isLink && node.target?.isInStore instead, which correctly skips store links while still running scripts for workspace links and store entries.
@manzoorwanijk manzoorwanijk requested a review from a team as a code owner February 23, 2026 06:27
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.

[BUG] install-strategy=linked runs postinstall scripts twice for store packages

1 participant