Skip to content

fix(libnpmexec): skip redundant reify for cached directory specs#9255

Merged
wraithgar merged 1 commit intonpm:latestfrom
manzoorwanijk:fix/npx-reify-directory-specs
Apr 17, 2026
Merged

fix(libnpmexec): skip redundant reify for cached directory specs#9255
wraithgar merged 1 commit intonpm:latestfrom
manzoorwanijk:fix/npx-reify-directory-specs

Conversation

@manzoorwanijk
Copy link
Copy Markdown
Contributor

npx unconditionally re-reifies file:/directory specs on every invocation, even when the package is already installed in the npx cache.
This happens because missingFromTree() has an early return for directory specs that bypasses the cache lookup entirely.
Registry packages correctly skip reify on cache hit by checking node.package.resolved === manifest._resolved, but directory specs never reach that check.

The fix makes two changes to missingFromTree() in libnpmexec/lib/index.js:

  1. The early return for directory specs is now scoped to non-npx trees (!isNpxTree), so the npx cache tree is actually consulted on subsequent runs.
  2. Added node.realpath === manifest._resolved as an alternative match condition, since file: spec nodes in the npx cache have undefined for package.resolved but their realpath contains the matching absolute path.

A regression test verifies that running exec twice with the same file: spec only triggers reify once (on the cold cache run).

References

Fixes #9251

@manzoorwanijk manzoorwanijk marked this pull request as ready for review April 17, 2026 16:47
@manzoorwanijk manzoorwanijk requested a review from a team as a code owner April 17, 2026 16:47
@wraithgar
Copy link
Copy Markdown
Member

Did some spot checking on this, and the only "bug" is one that already exists, namely if you use install-links with npx explicitly, the file ref contents will not be updated if the source package changes.

Everything else seems to work as expected.

@wraithgar wraithgar merged commit e9b0157 into npm:latest Apr 17, 2026
18 checks passed
github-actions bot pushed a commit that referenced this pull request Apr 17, 2026
`npx` unconditionally re-reifies `file:`/directory specs on every
invocation, even when the package is already installed in the npx cache.
This happens because `missingFromTree()` has an early return for
directory specs that bypasses the cache lookup entirely.
Registry packages correctly skip reify on cache hit by checking
`node.package.resolved === manifest._resolved`, but directory specs
never reach that check.

The fix makes two changes to `missingFromTree()` in
`libnpmexec/lib/index.js`:

1. The early return for directory specs is now scoped to non-npx trees
(`!isNpxTree`), so the npx cache tree is actually consulted on
subsequent runs.
2. Added `node.realpath === manifest._resolved` as an alternative match
condition, since `file:` spec nodes in the npx cache have `undefined`
for `package.resolved` but their `realpath` contains the matching
absolute path.

A regression test verifies that running `exec` twice with the same
`file:` spec only triggers `reify` once (on the cold cache run).

## References

Fixes #9251

(cherry picked from commit e9b0157)
@github-actions
Copy link
Copy Markdown
Contributor

🎉 Backport to release/v11 created: #9256

wraithgar pushed a commit that referenced this pull request Apr 17, 2026
Backport of #9255 to `release/v11`.

Co-authored-by: Manzoor Wani <manzoorwani.jk@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] npx always re-reifies directory/file: specs even when already cached

2 participants