Description
Version
v22.5.1
Platform
Linux PIG2016 5.15.153.1-microsoft-standard-WSL2 #1 SMP Fri Mar 29 23:14:13 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
Subsystem
npm
What steps will reproduce the bug?
- Download the latest Node.js tarball from the website
wget https://nodejs.org/dist/v22.5.1/node-v22.5.1-linux-x64.tar.xz
- Extract the Node.js tarball to your testing folder
tar xf node-v22.5.1-linux-x64.tar.xz -C ~/testing123
- Make sure you REMOVE any previous Node.js installation from your PATH
export PATH=$(echo "$PATH" | tr ":" "\n" | grep -v node | tr "\n" ":")
replacegrep -v node
withgrep -v /your/node/bin
- Confirm that
command -v node
returns nothing - Make sure
~/testing123/bin/node --version
works - Try to run
~/testing/bin/npm --version
. It fails.
$ command -V node
bash: command: node: not found
$ ~/testing123/bin/npm --version
/usr/bin/env: ‘node’: No such file or directory
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?
$ command -V node
bash: command: node: not found
$ ~/testing123/bin/npm --version
/usr/bin/env: ‘node’: No such file or directory
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
- ...so
~/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
- It performs a PATH lookup to find
node
- It fails.
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!
Activity