Skip to content

fix(libnpmexec): install npx cache despite dryRun or packageLockOnly - #10135

Open
ljharb wants to merge 1 commit into
npm:latestfrom
ljharb:libnpmexec-ignore-dry-run
Open

ljharb wants to merge 1 commit into
npm:latestfrom
ljharb:libnpmexec-ignore-dry-run

Conversation

@ljharb

@ljharb ljharb commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

When npm exec/npx or npm init <initializer> needs a package that is not installed, libnpmexec installs it to the npx cache and then runs its bin. If dryRun or packageLockOnly is set, Arborist skips that install, so the bin is missing and the command fails, even though the user never asked for the exec itself to be a dry run.

This happens without anyone passing those flags to npx directly: lifecycle scripts inherit the parent command's config as npm_config_* environment variables, so a prepublishOnly script that runs npx some-tool fails under npm publish --dry-run, because it sees npm_config_dry_run=true.

#4843 fixed this for packageLockOnly in npm exec only, by overriding it in lib/commands/exec.js. npm init <initializer> calls libnpmexec too, and still had the bug for both flags, and npm exec still had it for dryRun. This moves that override into libnpmexec, where the npx cache's Arborist is created, and extends it to dryRun, so every caller gets it. The existing npm exec packageLockOnly test still passes, and there are new tests in libnpmexec for both flags and in npm exec for dry-run.

…LockOnly is set

When `npm exec`/`npx` or `npm init <initializer>` needs a package that is not installed, libnpmexec installs it to the npx cache and then runs its bin. If `dryRun` or `packageLockOnly` is set, Arborist skips that install, so the bin is missing and the command fails, even though the user never asked for the exec itself to be a dry run.

This happens without anyone passing those flags to `npx` directly: lifecycle scripts inherit the parent command's config as `npm_config_*` environment variables, so a `prepublishOnly` script that runs `npx some-tool` fails under `npm publish --dry-run`, because it sees `npm_config_dry_run=true`.

npm#4843 fixed this for `packageLockOnly` in `npm exec` only, by overriding it in `lib/commands/exec.js`. `npm init <initializer>` calls libnpmexec too, and still had the bug for both flags, and `npm exec` still had it for `dryRun`. This moves that override into libnpmexec, where the npx cache's Arborist is created, and extends it to `dryRun`, so every caller gets it. The existing `npm exec` `packageLockOnly` test still passes, and there are new tests in libnpmexec for both flags and in `npm exec` for `dry-run`.
@ljharb
ljharb requested a review from a team as a code owner October 15, 2026 23:29
@ljharb ljharb changed the title fix(libnpmexec): install to the npx cache even when dryRun or packageLockOnly is set fix(libnpmexec): install npx cache despite dryRun or packageLockOnly Oct 15, 2026
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.

1 participant