npm-run-all icon indicating copy to clipboard operation
npm-run-all copied to clipboard

Broken with npm@7 when using npx ("Need to install the following packages: run")

Open Domiii opened this issue 4 years ago • 12 comments

After upgrading to npm@7, using npx npm-run-all ... stops execution and asks the user to install some run package (not a thing! don't do it!).

Example Command:

C:\Users\useruser\code\projectname>npx npm-run-all my:script

Need to install the following packages: run Ok to proceed?

Log reveals that execution is broken:

0 verbose cli 'C:\Users\useruser\AppData\Local\Volta\tools\image\node\16.0.0\node_modules\npm\bin\npm-cli.js', 0 verbose cli 'exec', 0 verbose cli '--', 0 verbose cli 'run', 0 verbose cli 'my:script'

Node@{15,16}, NPM@7 (via Volta) OS: Windows 10

Analysis

This happens because run-task.js determines npmPath from the execution of itself. However, in the latest version, if using npx, it will actually resolve to npx-cli.js which then tries to execute npx run ... (instead of npm run ...).

Workaround

Don't use npx. If (like in my case), the binaries did not get linked properly, use this instead:

node node_modules/npm-run-all/bin/npm-run-all -p script1 script2

For a shortcut, you can add the following to your package.json -> scripts:

"nra": "node node_modules/npm-run-all/bin/npm-run-all"

and then:

npm run nra -- -p script1 script2

Domiii avatar May 04 '21 07:05 Domiii

I have the same issue on Mac OS Big Sur as well. If you accidently say yes to install run then it continues to try to consider each script name as a file module and as expected it can't find it.

$ npx npm-run-all --parallel "test:*"
# should run test:unit and test:lint scripts

instead,

Starting: test:v2
internal/modules/cjs/loader.js:883
  throw err;
  ^

Error: Cannot find module 'Error: Cannot find module '/Users/username/project/test:unit'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:880:15)
    at Function.Module._load (internal/modules/cjs/loader.js:725:27)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
    at internal/main/run_main_module.js:17:47 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}

codejedi365 avatar May 14 '21 04:05 codejedi365

The workaround that worked for me was to include an explicit reference to npm with --npm-path npm:

So my package.json looks like:

"scripts": {
  "do:all-the-things": "npx npm-run-all --npm-path npm do:a-thing do:another-thing",
  "do:a-thing": "echo 'thing'",
  "do:another-thing": "echo 'thing'"
}

elwinschmitz avatar May 25 '21 14:05 elwinschmitz

The same issue, when running npx -y ts-node --project ./helpers/tsconfig.json "./helpers/spell-check.ts" and using NodeAPI in spell-check.ts.

Using const options: { npmPath: "npm" } helped, thanks @elwinschmitz !

Spent 1.5 hours debugging on Teams call... For some reason, it didn't ask for run to be installed. Maybe, because I was running npx with -y flag? Or because my colleague accepted installation? Not sure, but the symptoms were pretty hard to debug. It said:

Watching C:\ws4\UMP\LicencingService\ClientApp and all sub-directories not excluded by your .gitignore. Will not monitor dotfiles.
Found & ignored ./DAT\npm\node_modules ; is listed in .gitignore
Found & ignored ./node_modules ; is listed in .gitignore

Starting: cspell

and the process never ended.

Maxim-Mazurok avatar Oct 11 '21 06:10 Maxim-Mazurok

This should be handled by the library here: https://github.com/mysticatea/npm-run-all/blob/bf91f94ce597aa61da37d2e4208ce8c48bc86673/lib/run-task.js#L157

something like:

// Required due to changes in npm@7+
let defaultNpmPath = process.env.npm_execpath;
if (defaultNpmPath && defaultNpmPath.endsWith('npx-cli.js')) {
  defaultNpmPath.replace(/npx-cli\.js$/, 'npm-cli.js');
}
const npmPath = options.npmPath || defaultNpmPath;

ejose19 avatar Oct 27 '21 23:10 ejose19

I use npx run-s blah1 blah2 ... all the time from the cli (actually with an even shorter alias) and this hasn't worked since we upgraded node to 16.13.1 a couple of weeks ago. The @Domiii workaround is helpful but does not work once you stray deeper under the package.json directory of the current project (something npx handles).

Edit: @elwinschmitz solution is working for me. Thanks.

mlandisbqs avatar Dec 16 '21 18:12 mlandisbqs

Forking @elwinschmitz's solution, you can instead avoid npx entirely:

"do:all-the-things": "npm-run-all do:a-thing do:another-thing",

JBallin avatar Feb 28 '22 23:02 JBallin

My use case relies on npx... I'm using npm like traditional "make" where I might want to run multiple targets from the cli, sequentially. example:

npx run-s --npm-path clean build install run

^-- where I might not want to have a dedicated package script for every permutation of targets

The alias is now working like this:

alias npr='npx run-s --npm-path npm'

(..although run-s occasionally loses a symlink after cleaning the node_modules and running npm install)

My team uses npm directly instead of relying on tools like grunt, etc. So the package.json already has a pretty comprehensive set of scripts that are responsible for building and running the code.

mlandisbqs avatar Mar 01 '22 14:03 mlandisbqs

@koba04 this might become a severe security vulnerability if someone figures out the way to put malicious code to the run npm package. Despite run is not updated for 7 years it has 50k+ downloads a week, probably the majority is because people don't pay attention and agree to install it or use npm in non-interactive environments (like Docker) where npx installs required packages automatically.

kanoshin avatar May 07 '22 23:05 kanoshin

This cropped up for me in the trufflesuite/truffle monorepo because we were running lerna bootstrap as npx lerna bootstrap to avoid the chicken/egg problem of needing to install lerna as a local dependency before you can bootstrap.

We're a yarn-only project, and switching that command to yarn exec lerna bootstrap worked around this issue.

benjamincburns avatar Jul 22 '22 04:07 benjamincburns

Swapping out the npx ... command for npm exec -- ... also seems to work around this problem.

benjamincburns avatar Jul 22 '22 04:07 benjamincburns

I'm open to landing a patch to the maintenance fork I have if anyone has a clue how to best fix: https://github.com/bcomnes/npm-run-all2/issues/93#issuecomment-1304280790

I might take a stab myself soon but figured I would put the offer out there in the meantime.

bcomnes avatar Nov 05 '22 02:11 bcomnes

Landed a fix for this: https://github.com/bcomnes/npm-run-all2/releases/tag/v6.0.4

bcomnes avatar Nov 09 '22 19:11 bcomnes