Nvm: node not found after install

Created on 2 Feb 2016  路  10Comments  路  Source: nvm-sh/nvm

v21@v21:~$ nvm install 5.0
Downloading https://nodejs.org/dist/v5.0.0/node-v5.0.0-linux-x64.tar.xz...
######################################################################## 100.0%
WARNING: checksums are currently disabled for node.js v4.0 and later
/home/v21/.nvm/versions/node/v5.0.0/bin/npm: 2: exec: /home/v21/.nvm/versions/node/v5.0.0/bin/node: not found
nvm is not compatible with the npm config "prefix" option: currently set to ""
Run 'nvm use --delete-prefix v5.0.0' to unset it.

Seeing the same error on every version I try. nvm version is 0.30.2. I'm running Ubuntu 12.04.5 LTS (GNU/Linux 4.1.5-x86_64-linode61 x86_64) with bash. I have an install of 0.10 still working via nvm.

the node executable is visible with ls:

v21@v21:~$ ls -alh /home/v21/.nvm/versions/node/v5.5.0/bin/
total 25M
drwxrwxr-x 2 v21 v21 4.0K Jan 21 00:59 .
drwxrwxr-x 6 v21 v21 4.0K Feb  2 01:22 ..
-rwxrwxr-x 1 v21 v21  25M Jan 21 00:59 node
lrwxrwxrwx 1 v21 v21   38 Jan 21 00:59 npm -> ../lib/node_modules/npm/bin/npm-cli.js
feature requests installing node pull request wanted

Most helpful comment

I can confirm this issue on systems with a 32bit userland / 64bit kernel. I'm using such a setup at my workplace because we have a memory constrained application where we don't want the overhead of 64bit pointers, but need a 64bit kernel for certain virtual machine providers. I think that there is a valid use case for wanting to install a node that doesn't match the output of uname, the big problem so far seems to be how to properly detect that.

One approach which works for me, but is specific to Debian and its derivatives is to ask dpkg what architecture it has, since it will be unlikely that a user has dpkg installing packages of a completely wrong arch. The following patch was all it took to get this working for Ubuntu:

diff --git a/nvm.sh b/nvm.sh
index ce5c6b5..75669a3 100644
--- a/nvm.sh
+++ b/nvm.sh
@@ -1135,7 +1135,13 @@ nvm_get_arch() {
       HOST_ARCH=$(isainfo -n)
     fi
   else
-     HOST_ARCH="$(uname -m)"
+    # On Debian and its derivatives, check to see if the
+    # userland is 32-bit according to DPKG output.
+    if command -v dpkg > /dev/null ; then
+      HOST_ARCH="$(dpkg --print-architecture)"
+    else
+      HOST_ARCH="$(uname -m)"
+    fi
   fi

   local NVM_ARCH

But this probably isn't a very widely applicable approach in general. Another approach might be to check getconf LONG_BIT, which will properly return "32" or "64", but I'd imagine that first you'd want to check to make sure you're on i686 or x86_64, because you could get those values from getconf but be on, say, ARM.

I guess my questions are:

  1. What would need to be done to make this work into a "proper" PR?
  2. Is getconf a good approach to take?
  3. Should we limit these checks to Linux? I'm not very familiar with getconf, though it does appear to be POSIX from what I can see.
  4. Should we limit them to i686/x86_64 architectures or try to also do this for things like ARM/ARM64?

All 10 comments

What's nvm debug print out?

oh, sorry:

v21@v21:~$ nvm debug
nvm --version: v0.30.2
$SHELL: /bin/bash
$HOME: /home/v21
$NVM_DIR: '$HOME/.nvm'
$PREFIX: ''
$NPM_CONFIG_PREFIX: ''
nvm current: none
which node: 
which iojs: 
which npm: 
npm config get prefix: The program 'npm' is currently not installed.  You can install it by typing:
sudo apt-get install npm
npm root -g: The program 'npm' is currently not installed.  You can install it by typing:
sudo apt-get install npm

@v21 is there any chance that your $HOME directory is a symlink? What happens if you run nvm use --delete-prefix v5.0.0?

No, not a symlink.

And running nvm use --delete-prefix v5.0.0 fails because it can't find node to run npm with - I think that error is a red herring from the fact that npm config get prefix fails (due to failing to find node).

v21@v21:~$ nvm use 5.5
/home/v21/.nvm/versions/node/v5.5.0/bin/npm: 2: exec: /home/v21/.nvm/versions/node/v5.5.0/bin/node: not found
nvm is not compatible with the npm config "prefix" option: currently set to ""
Run `nvm use --delete-prefix v5.5.0` to unset it.
v21@v21:~$ nvm use --delete-prefix v5.5.0
/home/v21/.nvm/versions/node/v5.5.0/bin/npm: 2: exec: /home/v21/.nvm/versions/node/v5.5.0/bin/node: not found
/home/v21/.nvm/versions/node/v5.5.0/bin/npm: 2: exec: /home/v21/.nvm/versions/node/v5.5.0/bin/node: not found

furthermore:

v21@v21:~$ file /home/v21/.nvm/versions/node/v5.5.0/bin/node
/home/v21/.nvm/versions/node/v5.5.0/bin/node: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.9, BuildID[sha1]=0xfb0ad7e15bdcb7775d22b17ed78cc2dc078c6343, not stripped
v21@v21:~$ ldd /home/v21/.nvm/versions/node/v5.5.0/bin/node
    not a dynamic executable

versus

v21@v21:~$ ldd /home/v21/.nvm/v0.10.38/bin/node
    linux-gate.so.1 =>  (0xf7753000)
    libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0xf773f000)
    librt.so.1 => /lib/i386-linux-gnu/librt.so.1 (0xf7736000)
    libstdc++.so.6 => /usr/lib/i386-linux-gnu/libstdc++.so.6 (0xf7650000)
    libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xf7624000)
    libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0xf7606000)
    libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0xf75eb000)
    libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7442000)
    /lib/ld-linux.so.2 (0x5660e000)
v21@v21:~$ file /home/v21/.nvm/v0.10.38/bin/node
/home/v21/.nvm/v0.10.38/bin/node: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x5a5763f0019882ca107bb44ca1c3b9d0535b021b, not stripped

getting to the root of the problem, i think:

v21@v21:~$ dpkg --print-architecture
i386
v21@v21:~$ arch
x86_64

I am fairly sure the problem is that nvm.sh's architecture detection doesn't account for the fact that you can run a 32 bit userland on a 64 bit kernel. Specifically, this bit here: https://github.com/creationix/nvm/blob/754a0d7c5b28d4b1ae2c5ad91f9db8b51f54df56/nvm.sh#L984

(why am I running a 32 bit userland on a 64 bit kernel? because Linode offered me a server upgrade. I didn't know I was til I started digging into this)

fwiw, modern nodes don't work on 32 bit systems, so that definitely might be causing some problems.

If you wanted to help write tests + a PR to account for this, that would be great!

I can confirm this issue on systems with a 32bit userland / 64bit kernel. I'm using such a setup at my workplace because we have a memory constrained application where we don't want the overhead of 64bit pointers, but need a 64bit kernel for certain virtual machine providers. I think that there is a valid use case for wanting to install a node that doesn't match the output of uname, the big problem so far seems to be how to properly detect that.

One approach which works for me, but is specific to Debian and its derivatives is to ask dpkg what architecture it has, since it will be unlikely that a user has dpkg installing packages of a completely wrong arch. The following patch was all it took to get this working for Ubuntu:

diff --git a/nvm.sh b/nvm.sh
index ce5c6b5..75669a3 100644
--- a/nvm.sh
+++ b/nvm.sh
@@ -1135,7 +1135,13 @@ nvm_get_arch() {
       HOST_ARCH=$(isainfo -n)
     fi
   else
-     HOST_ARCH="$(uname -m)"
+    # On Debian and its derivatives, check to see if the
+    # userland is 32-bit according to DPKG output.
+    if command -v dpkg > /dev/null ; then
+      HOST_ARCH="$(dpkg --print-architecture)"
+    else
+      HOST_ARCH="$(uname -m)"
+    fi
   fi

   local NVM_ARCH

But this probably isn't a very widely applicable approach in general. Another approach might be to check getconf LONG_BIT, which will properly return "32" or "64", but I'd imagine that first you'd want to check to make sure you're on i686 or x86_64, because you could get those values from getconf but be on, say, ARM.

I guess my questions are:

  1. What would need to be done to make this work into a "proper" PR?
  2. Is getconf a good approach to take?
  3. Should we limit these checks to Linux? I'm not very familiar with getconf, though it does appear to be POSIX from what I can see.
  4. Should we limit them to i686/x86_64 architectures or try to also do this for things like ARM/ARM64?

@oslerw architecture support is one of the things I'm OK with having have lots of platform-specific detections in. The main concern is testability - it's really hard to test these things, and I'd want to have lots of confidence that no current platforms that work, would stop working. getconf being POSIX is excellent, but I have no idea if that's the philosophically correct thing to be checking.

This is related to #672

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ksmithut picture ksmithut  路  3Comments

dtgriscom picture dtgriscom  路  4Comments

raitucarp picture raitucarp  路  3Comments

cdelorme picture cdelorme  路  5Comments

gsklee picture gsklee  路  4Comments