nvm: sourcing nvm.sh exits with code 3 when .nvmrc is present and version is not installed

When I source nvm.sh like . "$HOME/.nvm/nvm.sh" for manual install and like . $(brew --prefix nvm)/nvm.sh, the exit code is 3.

Even though nvm works after that, in bash scripts with set -e, the script stops there, since the command exits with a non-zero value.

Is there a reason this fails? Is there a reason it exits with 3, if it’s not an actual failure? What can we do about that?

Some extra info:

Details
nvm --version: v0.34.0
$TERM_PROGRAM: iTerm.app
$SHELL: /bin/zsh
$SHLVL: 1
$HOME: /Users/pvinis
$NVM_DIR: '$HOME/.nvm'
$PATH: $HOME/.gem/ruby/2.5.1/bin:$HOME/.rubies/ruby-2.5.1/lib/ruby/gems/2.5.0/bin:$HOME/.rubies/ruby-2.5.1/bin:$NVM_DIR/versions/node/v11.0.0/bin:$HOME/.config/yarn/global/node_modules/.bin:$HOME/.yarn/bin:$HOME/Library/Python/3.7/bin:$HOME/.fastlane/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/MacGPG2/bin:/opt/X11/bin:$HOME/.rvm/bin
$PREFIX: ''
$NPM_CONFIG_PREFIX: ''
$NVM_NODEJS_ORG_MIRROR: ''
$NVM_IOJS_ORG_MIRROR: ''
shell version: 'zsh 5.3 (x86_64-apple-darwin18.0)'
uname -a: 'Darwin 18.2.0 Darwin Kernel Version 18.2.0: Mon Nov 12 20:24:46 PST 2018; root:xnu-4903.231.4~2/RELEASE_X86_64 x86_64'
OS version: Mac 10.14.2 18C54
curl: /usr/bin/curl, curl 7.54.0 (x86_64-apple-darwin18.0) libcurl/7.54.0 LibreSSL/2.6.4 zlib/1.2.11 nghttp2/1.24.1
wget: not found
git: /usr/local/bin/git, git version 2.19.1
grep: /usr/bin/grep, grep (BSD grep) 2.5.1-FreeBSD
awk: /usr/bin/awk, awk version 20070501
sed: illegal option -- -
usage: sed script [-Ealn] [-i extension] [file ...]
       sed [-Ealn] [-i extension] [-e script] ... [-f script_file] ... [file ...]
sed: /usr/bin/sed,
cut: illegal option -- -
usage: cut -b list [-n] [file ...]
       cut -c list [file ...]
       cut -f list [-s] [-d delim] [file ...]
cut: /usr/bin/cut,
basename: illegal option -- -
usage: basename string [suffix]
       basename [-a] [-s suffix] string [...]
basename: /usr/bin/basename,
rm: illegal option -- -
usage: rm [-f | -i] [-dPRrvW] file ...
       unlink file
rm: /bin/rm,
mkdir: illegal option -- -
usage: mkdir [-pv] [-m mode] directory ...
mkdir: /bin/mkdir,
xargs: illegal option -- -
usage: xargs [-0opt] [-E eofstr] [-I replstr [-R replacements]] [-J replstr]
             [-L number] [-n number [-x]] [-P maxprocs] [-s size]
             [utility [argument ...]]
xargs: /usr/bin/xargs,
nvm current: v11.0.0
which node: $NVM_DIR/versions/node/v11.0.0/bin/node
which iojs: iojs not found
which npm: $NVM_DIR/versions/node/v11.0.0/bin/npm
npm config get prefix: $NVM_DIR/versions/node/v11.0.0
npm root -g: $NVM_DIR/versions/node/v11.0.0/lib/node_modules
  • nvm ls output:
Details
        v8.12.0
       v10.12.0
->      v11.0.0
         system
default -> v11 (-> v11.0.0)
node -> stable (-> v11.0.0) (default)
stable -> 11.0 (-> v11.0.0) (default)
iojs -> N/A (default)
unstable -> N/A (default)
lts/* -> lts/dubnium (-> N/A)
lts/argon -> v4.9.1 (-> N/A)
lts/boron -> v6.14.4 (-> N/A)
lts/carbon -> v8.12.0
lts/dubnium -> v10.13.0 (-> N/A)
  • How did you install nvm? (e.g. install script in readme, Homebrew): Tried both. I mostly do from brew though, since it’s easier.

  • What steps did you perform? source the file

  • What happened? worked, but exits with non-zero value

  • What did you expect to happen? to exit with a 0 value since everything seemingly went well

  • Is there anything in any of your profile files (.bashrc, .bash_profile, .zshrc, etc) that modifies the PATH? I ran this without any $PATH alterations. In general I don’t have anything in there that touch nvm. Only to include brew stuff.

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Reactions: 4
  • Comments: 50 (20 by maintainers)

Commits related to this issue

Most upvoted comments

I found the reproducible way!

With nvm not in the system, uninstalled, cleared etc, no rc files, no nodes installed, try this:

  • go in a project dir with a .nvmrc
  • install nvm
  • source the nvm.sh file. it exits with code 3 that comes from https://github.com/creationix/nvm/blob/master/nvm.sh#L2944. nvm is correctly sourced, and works fine, but it prints that i need run nvm install which makes sense, but also returns with 3.

Basically, the problem here is sourcing nvm in a dir that has a .nvmrc in it. If I install and source outside, then go in the dir, it’s fine, and when I do nvm use it will complain and return 3, which is great.

I don’t know how this should be handled. I am basically trying to setup a project with ci, and in the ci I am already in the dir, and I install nvm, then source nvm, then nvm install, then nvm use. This order would work if sourcing would not try to do nvm use inside it I’m guessing.

What do you think?

omg I changed all numbers to unique ones (except the 312 :p) screen shot 2019-01-20 at 09 25 01 and it exits with 0.

I’ll start putting them back to 3 and see how when it breaks again.

I wanted to install nvm in a CI/CD environment in a docker image. It took me ~2-3 hours, to figure out what the problem is. I had only an exit code 3. Without a proper error message what the problem is, and how to solve it. In the nvm.sh there are 2 exit(3) occurrences and 23 return 3 occurrences.

I totally agree with the suggestions made by @pkalliok-aiven commented on Aug 27 2021.

For me the source "${NVM_DIR}/nvm.sh" --install solved the problem.

Right - the issue is that nvm expects that if an .nvmrc file is present with a node version in it, that before cd-ing into that directory, you’d source nvm. So, in your case, you can change to this:

          command: |
            curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
            echo 'export NVM_DIR="$HOME/.nvm"' >> $BASH_ENV
            echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" --install' >> $BASH_ENV
            source $BASH_ENV

(note that nvm alias default just echoes the current default alias, and that the nvm use default seems unnecessary)

Still running into this issue with v0.39.4. My workaround is to rename .nvmrc, source nvm, then rename back. This is my Makefile target:

nvm:
	# Have to rename .nvmrc then source nvm or it errors, see https://github.com/nvm-sh/nvm/issues/1985#issuecomment-456022013
	mv .nvmrc .nvmrc_temp

	# Need source nvm this way in make, see https://github.com/nvm-sh/nvm/issues/1446#issuecomment-816446454
	. ${NVM_DIR}/nvm.sh && mv .nvmrc_temp .nvmrc && nvm install && nvm use 

brew or manual, both give me this exit code.

From what I read here, the “real” problem is that nvm is reporting an error situation (the node version requested in .nvmrc is not found on the system), but it’s not telling very clearly what’s going on. Some suggestions that would improve the situation:

  • change nvm so that sourcing nvm.sh does not read .nvmrc at all (above it reads that this breaks use cases, but OTOH the installation documents don’t say that sourcing nvm.sh would do anything else than making the nvm commands available)
  • document in the installation instructions that sourcing nvm.sh in a directory with a .nvmrc can produce different results from a “clean” sourcing
  • add error messages like “.nvmrc asks for version xxx, but that’s not available on your system - please consider specifying --install
  • add at least some kind of hint that what nvm.sh is supposed to do - which is making the nvm commands available - was actually successful even though it returned 3.

Hm, ok on my home macbook its 0 exit even with a freshly installed one. That’s good. Then I’ll check tomorrow at work with the problematic machine, and see what could be the issue.

@omarrelativity i think this warrants a separate issue, since those sourcing options should work. mind filing it?

I tried both options already, still get Error 3:

nvm-install:
	. ${NVM_DIR}/nvm.sh --install
	
nvm-no-use:
	. ${NVM_DIR}/nvm.sh --no-use

ah, the default alias takes precedence over .nvmrc when present. If you nvm unalias default you should be closer to the state CI is in.

It would break other features, unfortunately 😕 specifically, the feature to auto-use the nvmrc version at source time, which in non-CI use cases, is already installed.

There may be a way to either detect CI, and do something different; or, only when sourcing nvm.sh, avoid failing when an nvmrc version is not present.

@ljharb got you, that makes sense! I used --install as you suggested, and it worked perfectly. 👍🏼

Do you think it would be possible to add a fix for this? Probably ignoring the .nvmrc file when nvm.sh is sourced? (I’m not sure if that would break other features, though 🤔). If not, probably it’s something worth adding to the documentation to help other folks understand what could cause this exit code 3 issue, WDYT? 🙂

I will try master out of curiosity 😄

Sorry to hear that 😃

I believe I’ve solved it with 58d0933f72c3b819d8180e3fe68b66201a87c0a4, so I’ll close.

I’ll try it.

Well, if the ci is using a node image, usually nvm is there already. If it’s booting a macos image though, nvm is probably missing, so the init happens, cds in my project and then I get control, when I would start installing nvm and other things that I need.

Thanks for your efforts! I’m looking forward to fixing this, and perhaps convincing me it’s time for unique exit codes 😄

that’s a good idea. I’ll try that tomorrow morning since I’m on my phone now.

Is there a reason actually that it returns the same number Ina few places? why not use different numbers for different places and different errors by default?

Note that nvm is not supported with homebrew - if you brew uninstall it, and install it the proper way (in the readme), do you see the same behavior?