nvm icon indicating copy to clipboard operation
nvm copied to clipboard

Installation fails on WSL when Windows host has npm installed and in PATH

Open omar-sobhy opened this issue 2 months ago • 3 comments

Operating system and version:

WSL (Ubuntu 24.04)

nvm debug output:

nvm --version: v0.40.3
$SHELL: /usr/bin/zsh
$SHLVL: 1
whoami: 'omar'
${HOME}: /home/omar
${NVM_DIR}: '${HOME}/.nvm'
${PATH}: ${NVM_DIR}/versions/node/v25.1.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/lib/wsl/lib:/mnt/c/Program Files/WindowsApps/MicrosoftCorporationII.WindowsSubsystemForLinux_2.6.1.0_x64__8wekyb3d8bbwe:/mnt/c/Program Files/Common Files/Oracle/Java/javapath:/mnt/c/Program Files (x86)/Common Files/Oracle/Java/java8path:/mnt/c/Program Files (x86)/Common Files/Oracle/Java/javapath:/mnt/c/ProgramData/Boxstarter:/mnt/c/Windows/system32:/mnt/c/Windows:/mnt/c/Windows/System32/Wbem:/mnt/c/Windows/System32/WindowsPowerShell/v1.0/:/mnt/c/Windows/System32/OpenSSH/:/mnt/c/Program Files (x86)/NVIDIA Corporation/PhysX/Common:/mnt/c/Program Files/WireGuard/:/mnt/c/Program Files/Calibre2/:/mnt/c/ProgramData/chocolatey/bin:/mnt/c/Program Files/nodejs/:/mnt/c/Program Files/dotnet/:/mnt/c/Program Files/NVIDIA Corporation/NVIDIA App/NvDLISR:/mnt/c/Program Files/Git/cmd:/mnt/c/Tools/FirefoxPWA/:/mnt/c/Program Files/Docker/Docker/resources/bin:/mnt/c/Program Files/FirefoxPWA/:/mnt/c/WINDOWS/system32:/mnt/c/WINDOWS:/mnt/c/WINDOWS/System32/Wbem:/mnt/c/WINDOWS/System32/WindowsPowerShell/v1.0/:/mnt/c/WINDOWS/System32/OpenSSH/:/mnt/c/Program Files/PowerShell/7/:/mnt/c/Tools/Python/Python3.13/Scripts/:/mnt/c/Tools/Python/Python3.13/:/mnt/c/Users/Omar/AppData/Local/Programs/Python/Launcher/:/mnt/c/Users/Omar/AppData/Local/pnpm:/mnt/c/Users/Omar/AppData/Local/Microsoft/WindowsApps:/mnt/c/Users/Omar/AppData/Local/Programs/Microsoft VS Code/bin:/mnt/c/Users/Omar/AppData/Roaming/npm:/mnt/c/Program Files/JetBrains/IntelliJ IDEA 2024.1.2/bin:/mnt/c/Tools/MiKTeX/miktex/bin/x64/:/mnt/c/users/omar/.local/bin:/mnt/c/users/omar/appdata/roaming/python/python313/scripts:/mnt/c/Users/Omar/.dotnet/tools:/mnt/c/Users/Omar/AppData/Local/Microsoft/WindowsApps
$PREFIX: ''
${NPM_CONFIG_PREFIX}: ''
$NVM_NODEJS_ORG_MIRROR: ''
$NVM_IOJS_ORG_MIRROR: ''
shell version: 'zsh 5.9 (x86_64-ubuntu-linux-gnu)'
uname -a: 'Linux 6.6.87.2-microsoft-standard-WSL2 #1 SMP PREEMPT_DYNAMIC Thu Jun 5 18:30:46 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux'
checksum binary: 'sha256sum'
OS version: Ubuntu 24.04.3 LTS
awk: /usr/bin/awk, GNU Awk 5.2.1, API 3.2, PMA Avon 8-g1, (GNU MPFR 4.2.1, GNU MP 6.3.0)
curl: /usr/bin/curl, curl 8.5.0 (x86_64-pc-linux-gnu) libcurl/8.5.0 OpenSSL/3.0.13 zlib/1.3 brotli/1.1.0 zstd/1.5.5 libidn2/2.3.7 libpsl/0.21.2 (+libidn2/2.3.7) libssh/0.10.6/openssl/zlib nghttp2/1.59.0 librtmp/2.3 OpenLDAP/2.6.7
wget: /usr/bin/wget, GNU Wget 1.21.4 built on linux-gnu.
git: /usr/bin/git, git version 2.43.0
grep: /usr/bin/grep, grep (GNU grep) 3.11
sed: /usr/bin/sed, sed (GNU sed) 4.9
cut: /usr/bin/cut, cut (GNU coreutils) 9.4
basename: /usr/bin/basename, basename (GNU coreutils) 9.4
rm: /usr/bin/rm, rm (GNU coreutils) 9.4
mkdir: /usr/bin/mkdir, mkdir (GNU coreutils) 9.4
xargs: /usr/bin/xargs, xargs (GNU findutils) 4.9.0
nvm current: none
which node: node not found
which iojs: iojs not found
which npm: /mnt/c/Program Files/nodejs//npm
npm config get prefix: C:\Users\Omar\AppData\Roaming\npm
npm root -g: C:\Users\Omar\AppData\Roaming\npm\node_modules

nvm ls output:

➜ nvm ls
            N/A
iojs -> N/A (default)
node -> stable (-> N/A) (default)
unstable -> N/A (default)

How did you install nvm?

Install script in readme

What steps did you perform?

  1. The Windows host has npm installed and in the PATH
  2. Run the command curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash

What happened?

Halfway into the installation, some npm errors were logged:

➜ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 16631  100 16631    0     0   129k      0 --:--:-- --:--:-- --:--:--  129k
=> Downloading nvm from git to '/home/omar/.nvm'
=> Cloning into '/home/omar/.nvm'...
remote: Enumerating objects: 383, done.
remote: Counting objects: 100% (383/383), done.
remote: Compressing objects: 100% (326/326), done.
remote: Total 383 (delta 43), reused 180 (delta 29), pack-reused 0 (from 0)
Receiving objects: 100% (383/383), 391.78 KiB | 1.30 MiB/s, done.
Resolving deltas: 100% (43/43), done.
* (HEAD detached at FETCH_HEAD)
  master
=> Compressing and cleaning up git repository

=> Appending nvm source string to /home/omar/.zshrc
=> Appending bash_completion source string to /home/omar/.zshrc
npm ERR! code ENOENT
npm ERR! syscall lstat
npm ERR! path C:\Users\Omar\AppData\Roaming\npm
npm ERR! errno -4058
npm ERR! enoent ENOENT: no such file or directory, lstat 'C:\Users\Omar\AppData\Roaming\npm'
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoent

npm ERR! A complete log of this run can be found in: C:\Users\Omar\AppData\Local\npm-cache\_logs\2025-11-06T07_26_45_419Z-debug-0.log
=> Close and reopen your terminal to start using nvm or run the following to use it now:

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion

What did you expect to happen?

I expect the script to install successfully.

Is there anything in any of your profile files that modifies the PATH?

My Windows PATH is modified to include the Windows global npm.

If you are having installation issues, or getting "N/A", what does curl -I --compressed -v https://nodejs.org/dist/ print out?


omar-sobhy avatar Nov 06 '25 07:11 omar-sobhy

Hmm, the install process shouldn't be invoking npm at all. However, I'd also expect that in WSL, you wouldn't have any windows programs in your PATH.

ljharb avatar Nov 07 '25 07:11 ljharb

it installs. but every restart it forgets. any solutions for that ?

mdabir1203 avatar Nov 20 '25 12:11 mdabir1203

Hmm, the install process shouldn't be invoking npm at all. However, I'd also expect that in WSL, you wouldn't have any windows programs in your PATH.

Honestly, it's a bit confusing how it actually works. I think I narrowed it down to a few things.

First, I just checked the node installation directory in Windows and there's a shell script named npm -- it's not an actual Windows binary. There's also a .cmd script named npm.cmd. I'm not really sure why the Windows version of node includes that npm shell script. Looking at the contents of that script, I think it's for compatibility with Cygwin-type environments or even WSL (see contents below)

#!/usr/bin/env bash

# This is used by the Node.js installer, which expects the cygwin/mingw
# shell script to already be present in the npm dependency folder.

(set -o igncr) 2>/dev/null && set -o igncr; # cygwin encoding fix

basedir=`dirname "$0"`

case `uname` in
  *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
esac

if [ `uname` = 'Linux' ] && type wslpath &>/dev/null ; then
  IS_WSL="true"
fi

function no_node_dir {
  # if this didn't work, then everything else below will fail
  echo "Could not determine Node.js install directory" >&2
  exit 1
}

NODE_EXE="$basedir/node.exe"
if ! [ -x "$NODE_EXE" ]; then
  NODE_EXE="$basedir/node"
fi
if ! [ -x "$NODE_EXE" ]; then
  NODE_EXE=node
fi

# this path is passed to node.exe, so it needs to match whatever
# kind of paths Node.js thinks it's using, typically win32 paths.
CLI_BASEDIR="$("$NODE_EXE" -p 'require("path").dirname(process.execPath)' 2> /dev/null)"
if [ $? -ne 0 ]; then
  # this fails under WSL 1 so add an additional message. we also suppress stderr above
  # because the actual error raised is not helpful. in WSL 1 node.exe cannot handle
  # output redirection properly. See https://github.com/microsoft/WSL/issues/2370
  if [ "$IS_WSL" == "true" ]; then
    echo "WSL 1 is not supported. Please upgrade to WSL 2 or above." >&2
  fi
  no_node_dir
fi
NPM_PREFIX_JS="$CLI_BASEDIR/node_modules/npm/bin/npm-prefix.js"
NPM_CLI_JS="$CLI_BASEDIR/node_modules/npm/bin/npm-cli.js"
NPM_PREFIX=`"$NODE_EXE" "$NPM_PREFIX_JS"`
if [ $? -ne 0 ]; then
  no_node_dir
fi
NPM_PREFIX_NPM_CLI_JS="$NPM_PREFIX/node_modules/npm/bin/npm-cli.js"

# a path that will fail -f test on any posix bash
NPM_WSL_PATH="/.."

# WSL can run Windows binaries, so we have to give it the win32 path
# however, WSL bash tests against posix paths, so we need to construct that
# to know if npm is installed globally.
if [ "$IS_WSL" == "true" ]; then
  NPM_WSL_PATH=`wslpath "$NPM_PREFIX_NPM_CLI_JS"`
fi
if [ -f "$NPM_PREFIX_NPM_CLI_JS" ] || [ -f "$NPM_WSL_PATH" ]; then
  NPM_CLI_JS="$NPM_PREFIX_NPM_CLI_JS"
fi

"$NODE_EXE" "$NPM_CLI_JS" "$@"

Second, WSL automagically appends your windows PATH to the WSL path (with paths translated, so for example C:/Program Files/nodejs turns into /mnt/c/Program Files/nodejs/). This is to ease usage of Windows tools from WSL. That explains why simply running npm calls the Windows version.

Also, I think I figured out why the installation process is calling npm in the first place. Looking at this line in install.sh, the nvm_check_global_modules function is called before nvm installs node. This function run npm list -g --depth=0. It seem this is the culprit -- I ran that command manually and it generated the same error:

npm error code ENOENT
npm error syscall lstat
npm error path C:\Users\Omar\AppData\Roaming\npm
npm error errno -4058
npm error enoent ENOENT: no such file or directory, lstat 'C:\Users\Omar\AppData\Roaming\npm'
npm error enoent This is related to npm not being able to find a file.
npm error enoent
npm error A complete log of this run can be found in: C:\Users\Omar\AppData\Local\npm-cache\_logs\2025-11-20T20_10_30_271Z-debug-0.log

I'm not really up for a dig through the node source code right now, but I'm going to assume it doesn't handle path translation properly when called from WSL.

I'm not sure what a good solution for this would be. You could check the output of which npm and report a warning if it starts with /mnt/. That sounds pretty brittle though (what if the user somehow has a symlink or something similar to a different path?). Another option would be checking the output of npm list for any Windows paths, but again I don't know how to do this properly. Could also just chalk it down to being an upstream issue with node.

Finally, here's the workaround I used to install nvm and node: I modified PATH before running the install script. This is pretty easy to do manually, but I used this command to automate it (not well-tested, use with care):

export PATH=`echo $PATH | tr ':' '\n' | grep -v "/mnt/c/Program Files/nodejs" | tr '\n' ':'`

omar-sobhy avatar Nov 20 '25 20:11 omar-sobhy