This problem does not happen on Windows because the npm.cmd wrapper is NOT just a simple symlink on Windows; instead it directly executes ${the_node_exe} ${the_cwd}/node_modules/npm/bin/npm-cli.js.
I think a good solution for this would be to change ./bin/npm in the release tarball for Linux (and macOS too, I assume?) to be a POSIX shell script similar to npm.cmd in the Windows release. It's already a (symlinked) shebang script #!/usr/bin/env node so a change to #!/bin/sh and exec ${the_cwd}/node ${the_cwd}/../lib/node_modules/npm/bin/npm-cli.js wouldn't be that much of a change.
OR to somehow get the npm-cli.js to check for a ../../../../bin/node executable and use that before performing a PATH lookup
Another scenario where this could cause an issue (conceivably; I'm just fishing at this point lol)
User is using ancient Ubuntu with Node.js v12
Download the Node.js v22 tarball to see if some project works with upgrading to Node.js v22 & npm v10 (don't add it to PATH)
Runs ./test-node22/bin/npm install and it fails because npm's JavaScript uses features that Node.js v12 doesn't have (because it ran using #!/usr/bin/env node, not the local ./test-node22/bin/node)
It'd be pretty trippy if npm in your local test Node.js v22 used an older v12 node version from your PATH to run itself or even run dependencies like prettier 😵
Admittedly all of these issues could be solved by saying "well just add it to your path and be done with it!". And that's true -- export PATH="$HOME/testing123/bin:$PATH" && ~/testing123/bin/npm would solve the problem.
However I contend that since this was solved on Windows it should be within the scope of Node.js to also solve the same problem on Linux (and macOS?) systems.
This would also make it easier to do something like:
Node.js v18 installed to ~/node-18; not in PATH
Node.js v22 installed to ~/node-22; not in PATH
~/.local/bin/node-18 symlinks to ~/node-18/bin/node
~/.local/bin/node-18-npm symlinks to ~/node-18/bin/npm
~/.local/bin/node-22 symlinks to ~/node-22/bin/node
~/.local/bin/node-22-npm symlinks to ~/node-22/bin/npm
And they wouldn't accidentally start using each other's node binaries!
Version
v22.5.1
Platform
Subsystem
npm
What steps will reproduce the bug?
wget https://nodejs.org/dist/v22.5.1/node-v22.5.1-linux-x64.tar.xz
tar xf node-v22.5.1-linux-x64.tar.xz -C ~/testing123
export PATH=$(echo "$PATH" | tr ":" "\n" | grep -v node | tr "\n" ":")
replacegrep -v node
withgrep -v /your/node/bin
command -v node
returns nothing~/testing123/bin/node --version
works~/testing/bin/npm --version
. It fails.How often does it reproduce? Is there a required condition?
Must NOT have a (compatible) Node.js binary available on PATH.
This problem does not happen on Windows.
What is the expected behavior? Why is that the expected behavior?
It should show me the version of npm, same as if I directly invoke
~/testing123/bin/node ~/testing123/lib/node_modules/npm/bin/npm-cli.js --version
What do you see instead?
Additional information
I think this is because:
~/testing123/bin/npm
is a symlink to../lib/node_modules/npm/bin/npm-cli.js
which is~/testing123/lib/node_modules/npm/bin/npm-cli.js
~/testing123/lib/node_modules/npm/bin/npm-cli.js
is directly executed when you run~/testing123/bin/npm
~/testing123/lib/node_modules/npm/bin/npm-cli.js
uses#!/usr/bin/env node
node
This problem does not happen on Windows because the
npm.cmd
wrapper is NOT just a simple symlink on Windows; instead it directly executes${the_node_exe} ${the_cwd}/node_modules/npm/bin/npm-cli.js
.I think a good solution for this would be to change
./bin/npm
in the release tarball for Linux (and macOS too, I assume?) to be a POSIX shell script similar tonpm.cmd
in the Windows release. It's already a (symlinked) shebang script#!/usr/bin/env node
so a change to#!/bin/sh
andexec ${the_cwd}/node ${the_cwd}/../lib/node_modules/npm/bin/npm-cli.js
wouldn't be that much of a change.OR to somehow get the npm-cli.js to check for a ../../../../bin/node executable and use that before performing a PATH lookup
Another scenario where this could cause an issue (conceivably; I'm just fishing at this point lol)
./test-node22/bin/npm install
and it fails because npm's JavaScript uses features that Node.js v12 doesn't have (because it ran using#!/usr/bin/env node
, not the local./test-node22/bin/node
)It'd be pretty trippy if
npm
in your local test Node.js v22 used an older v12node
version from yourPATH
to run itself or even run dependencies likeprettier
😵Admittedly all of these issues could be solved by saying "well just add it to your path and be done with it!". And that's true --
export PATH="$HOME/testing123/bin:$PATH" && ~/testing123/bin/npm
would solve the problem.However I contend that since this was solved on Windows it should be within the scope of Node.js to also solve the same problem on Linux (and macOS?) systems.
This would also make it easier to do something like:
~/.local/bin/node-18
symlinks to~/node-18/bin/node
~/.local/bin/node-18-npm
symlinks to~/node-18/bin/npm
~/.local/bin/node-22
symlinks to~/node-22/bin/node
~/.local/bin/node-22-npm
symlinks to~/node-22/bin/npm
And they wouldn't accidentally start using each other's
node
binaries!