nvm: nvm is not compatible with the "PREFIX" environment variable: currently set to "/usr/local"

  • Operating system and version:

  • nvm debug output:

rockchalkwushock in mashaeltsova-photography on development [+?] $ nvm debug
nvm --version: v0.33.6
$TERM_PROGRAM: vscode
$SHELL: /bin/bash
$HOME: /Users/rockchalkwushock
$NVM_DIR: '$HOME/.nvm'
$PREFIX: ''
$NPM_CONFIG_PREFIX: ''
$NVM_NODEJS_ORG_MIRROR: ''
$NVM_IOJS_ORG_MIRROR: ''
shell version: 'GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)'
uname -a: 'Darwin 17.0.0 Darwin Kernel Version 17.0.0: Thu Aug 24 21:48:19 PDT 2017; root:xnu-4570.1.46~2/RELEASE_X86_64 x86_64'
OS version: Mac 10.13 17A405
curl: /usr/bin/curl, curl 7.54.0 (x86_64-apple-darwin17.0) libcurl/7.54.0 LibreSSL/2.0.20 zlib/1.2.11 nghttp2/1.24.0
wget: not found
git: /usr/local/bin/git, git version 2.14.3
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: v8.8.1
which node: $NVM_DIR/versions/node/v8.8.1/bin/node
which iojs:
which npm: $NVM_DIR/versions/node/v8.8.1/bin/npm
npm config get prefix: $NVM_DIR/versions/node/v8.8.1
npm root -g: $NVM_DIR/versions/node/v8.8.1/lib/node_modules
  • nvm ls output:
rockchalkwushock in mashaeltsova-photography on development [+?] $ nvm ls
->       v8.8.1
default -> node (-> v8.8.1)
node -> stable (-> v8.8.1) (default)
stable -> 8.8 (-> v8.8.1) (default)
iojs -> N/A (default)
lts/* -> lts/boron (-> N/A)
lts/argon -> v4.8.5 (-> N/A)
lts/boron -> v6.11.5 (-> N/A)
rockchalkwushock in mashaeltsova-photography on development [+?] $
  • How did you install nvm? (e.g. install script in readme, homebrew): install_script
  • What steps did you perform?
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.6/install.sh | bash

# inside .bash_profile
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

source .bashrc
nvm install node
nvm use node
  • What happened? When trying to commit to git using husky & lint-staged I am getting the following output:
nvm is not compatible with the "PREFIX" environment variable: currently set to "/usr/local"
Run `unset PREFIX` to unset it.
Found '/Users/rockchalkwushock/Desktop/MEP/mashaeltsova-photography/.nvmrc' with version <8.8.1>
nvm is not compatible with the "PREFIX" environment variable: currently set to "/usr/local"
Run `unset PREFIX` to unset it.
Found '/Users/rockchalkwushock/Desktop/MEP/mashaeltsova-photography/.nvmrc' with version <8.8.1>
nvm is not compatible with the "PREFIX" environment variable: currently set to "/usr/local"
Run `unset PREFIX` to unset it.
.git/hooks/pre-commit: line 49: node: command not found
husky > npm run -s precommit (node )

env: node: No such file or directory

husky > pre-commit hook failed (add --no-verify to bypass)
/Users/rockchalkwushock/Desktop/MEP/mashaeltsova-photography/node_modules/commitizen/dist/cli/strategies/git-cz.js:102
        throw error;
        ^

Error: git exited with error code 1
    at ChildProcess.<anonymous> (/Users/rockchalkwushock/Desktop/MEP/mashaeltsova-photography/node_modules/commitizen/dist/git/commit.js:50:26)
    at emitTwo (events.js:125:13)
    at ChildProcess.emit (events.js:213:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
The script called "commit" which runs "git cz" failed with exit code 1 https://github.com/kentcdodds/nps/blob/v5.7.1/other/ERRORS_AND_WARNINGS.md#failed-with-exit-code
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
  • What did you expect to happen?

Commit and push up as I have been doing with no issues. Had zero problems on Saturday. No updates were ran in between then and now. I have since upgraded nvm from 0.33.4 to 0.33.6 and upgraded node 8.8.0 to 8.8.1. git has always been installed with homebrew and has caused me not issues before when working with nvm.

  • Is there anything in any of your profile files (.bashrc, .bash_profile, .zshrc, etc) that modifies the PATH?
PATH=/Users/rockchalkwushock/.nvm/versions/node/v8.8.1/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/rockchalkwushock/.config/yarn/global/bin

# in .exports
# Set Yarn Global Binary Path.
export PATH="$PATH:`yarn global bin`";

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 7
  • Comments: 63 (20 by maintainers)

Commits related to this issue

Most upvoted comments

No need to unset anything… This behavior happens when you have more than 1 installation of npm/yarn. I had 3 😄. Here are the steps I performed in order to solve it:

  1. Delete all installations of npm and yarn.
brew uninstall npm 
brew uninstall yarn

npm uninstall yarn

uninstall npm. See https://docs.npmjs.com/cli/v7/using-npm/removal.

  1. Make sure you have a working nvm. which npm should return something like this /Users/*******/.nvm/versions/node/v14.17.0/bin/npm and not a path that starts with /usr/local.

  2. ONLY AFTER THAT, install yarn globally with npm install -g yarn.

I solved it by running:

nvm unalias default

I had this issue trying to use nvm in Termux, which is a prefixed Linux environment for Android.

I got around it by running:

PREFIX= nvm use --delete-prefix stable

This didn’t unset the PREFIX environment variable, or even delete the prefix npm config (npm config get prefix still returns the old prefix), but it did let nvm run properly.

No need to unset anything… This behavior happens when you have more than 1 installation of npm/yarn. I had 3 😄. Here are the steps I performed in order to solve it:

  1. Delete all installations of npm and yarn.
brew uninstall npm 
brew unistall yarn

npm uninstall yarn

uninstall npm. See https://docs.npmjs.com/cli/v7/using-npm/removal.

  1. Make sure you have a working nvm. which npm should return something like this /Users/*******/.nvm/versions/node/v14.17.0/bin/npm and not a path that starts with /usr/local.
  2. ONLY AFTER THAT, install yarn globally with npm install -g yarn.

This was the problem I was having.

Thanks a lot for this, I very much appreciate it!

Updating nvm to 0.38.0 solved it for me

@luxueyan I never found a solution. I just installed node from apt, instead of using nvm.

Not really sure why this was closed as it is clearly still an issue.

100% default system here, I just bought a new iMac pro… XCode then this was my first installations. I have installed nvm many times on other systems and now I run into this…

Nothing in my files or setup that could possibly set PREFIX so its being done somewhere invisible to me

Last login: Sun Mar 11 21:20:45 on ttys008
nvm is not compatible with the "PREFIX" environment variable: currently set to "/usr/local"
Run `unset PREFIX` to unset it.
Bradens-iMac-Pro-2:~ bradennapier$ 

with my .bashrc

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

and my .bash_profile

source ~/.bashrc

I have reinstalled nvm, i have tried everything. I have never installed node on the system.

This appears to happen by doing a npm install -g ____ as a default issue

Perhaps Node 9.8.0 uses PREFIX?

I literally have no idea how that is set but i have about 100 env vars set by default in terminal seemingly by XCode

I would also point out that OSX’s default Terminal.app does not work however iTerm does work.

Having the same issue. With no solution at all

I spent a few hours to figure out hot to do it on my Mac Mini

  • delete any installed node except of the nvm https://stackabuse.com/how-to-uninstall-node-js-from-mac-osx/
  • edit ~/.zshrc nano ~/.zshrc and delete lines with export NVM_DIR... and any other which contains $NVM_DIR
  • install nvm again curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.0/install.sh | bash
  • check node nvm --version
  • if not found install it
  • Install the latest LTS version with nvm install --lts
  • use the latest LTS version with nvm use --lts

Profit

@wilsolutions the solution is to unset PREFIX.

When I try to configure husky pre commit hook to commitlint, I get error:

image

I try to create .huskyrc with NVM load script:


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

I get more errors: image

My solution


When I try to add node to PATH in .huskyrc directly, it’s works fine

export PATH=/home/righthaze/.nvm/versions/node/v16.16.0/bin:$PATH

where - v16.16.0 my node version

image

node/npm work fine in Termux when installed from apt, just not when installed from nvm.

I have added support in termux-app to export $TERMUX__PREFIX as well and can move our packages repo to use it as well in future, but we have millions of users and they would still be using $PREFIX in their custom scripts. Third party, including multi platform ones also use $PREFIX, likely to check if running in termux if its set to /data/data/com.termux/files/user. So even if I wanted to, its unlikely that we can ever remove it, or at the very least for a long while. We can deprecate $PREFIX in next version and put out an advisory to users to use $TERMUX__PREFIX instead, pretty much all we can do at this point.

As for solving issues of termux and other platforms where $PREFIX may be set to something different, wouldn’t it be much simpler to just patch the receivers node/npm/nvm instead of tonne of others repos/scripts? Can’t something like $NPM_IGNORE_LEGACY_PREFIX be added to ignore using $PREFIX if its already set, and to use $NPM_PREFIX as well or something. The node prefix and node root -g can be patched appropriately. Or are other node packages and support tools using $PREFIX directly somehow without the commands? I don’t use node myself, so my knowledge is lacking in that area.

If I am not mistaken, the patches should be pretty simple to set globalPrefix.

https://docs.npmjs.com/cli/v8/commands/npm-root

https://docs.npmjs.com/cli/v9/commands/npm-prefix

https://github.com/search?q=org%3Anpm+env.PREFIX&type=code

https://github.com/search?q=org%3Anodejs+%24PREFIX&type=code

https://github.com/search?q=org%3Anpm+%24PREFIX&type=code&p=2

https://github.com/nodejs/node/blob/67a9ed3f7f3c02cd908f98ac375bf1041a64ec70/Makefile#L189

https://github.com/nodejs/node/blob/67a9ed3f7f3c02cd908f98ac375bf1041a64ec70/lib/internal/modules/cjs/loader.js#L1380

@ljharb What would be the point of creating a separate issue? This issue already states the problem. You said:

nvm is incompatible with having a prefix, so it seems like Termux is, at the moment, incompatible with nvm.

Termux isn’t going to stop using a PREFIX, as it’s necessary to their implementation on Android, and nvm isn’t going to support an environment with PREFIX, or this issue wouldn’t have been closed, so as far as I can tell, ne’er the twain shall meet.

@ljharb I made a mistake here, my issue was specifically with husky (putting the right input formats) and I blamed it on nvm, sorry!

@ljharb That’s fine for nvm, but I’m saying that I have to have PREFIX set when using Termux, otherwise other apps won’t work properly. It’s just the way Termux was built.

So, by doing PREFIX= nvm use --delete-prefix stable, it basically unset PREFIX only for nvm. npm and npx then worked after that, although node did not.

But, I can’t just add unset PREFIX in my .bashrc and use everything as usual. Everything else will break.

I understand that part, but since termux doesn’t keep old versions of node …

nvm itself installs old versions of node/npm. It does not leverage pkg or apt, so Termux would absolutely keep old versions of node installed by nvm, as @ljharb said.

I guess then suggested fix would only be useful for npm, but not for nvm.

It would be useful if you patch a couple of major versions of npm and publish new minor versions of all (LTS) versions of node to ship with the new npm. This wouldn’t fix the entire problem, but would enable at least the latest LTS versions to function in Termux with nvm, which would be a big win, already.

Even if we fix it today for future versions of node / npm only, it would be at least no problem in half or full a decade.

I see, I don’t know the details of nvm, so I am probably missing things regarding the issue. But wouldn’t providing the latest version of major npm/node releases that have been patched and using $NPM_PREFIX fix the issue for users who install the latest version and any future versions?

nvm is a version manager for node and npm that allows to install any versions of node/npm at the same time by switching between environments. Every node version has a specific npm version that it ships with. Simply fixing the issue in the latest npm version will fix the issue in the future, but older projects that require older node versions still won’t run in Termux.

It would be needed if user wants to engage the current third condition and $PREFIX is already set, like in termux, there would be cases where npm is used without nvm setting prefix.

Yes you are right, I missed that final else if statement.

To be clear, it’s npm, not node, that looks at PREFIX.

The node makefile is using it too.

https://github.com/nodejs/node/blob/67a9ed3f7f3c02cd908f98ac375bf1041a64ec70/Makefile#L189

There are far more installations of npm than termux, without any doubt, so the easiest would be patching termux.

Sure. But why would that matter? Users can use the new version if they want the fix and it will behave just as before without any breaking changes, and $PREFIX will be used as well, unless $NPM_IGNORE_LEGACY_PREFIX is set. Patching couple of functions in npm should surely be easier than patching countless user scripts and third party softwares and multiple termux packages. And like I said, even if termux internal packages are patched, it doesn’t matter too much, its like a linux distribution, users using $PREFIX would still exist unless they move.

But I guess, if termux internal packages are patched, then it should allow users who want to unset $PREFIX to be able to do that as long as they don’t use third party software that requires it. I also don’t know if even patching 100% of termux internal packages would even be possible without any issues.

And adding a alternate variable (like $NPM_PREFIX) to solve compatibility or conflict issues from old software is standard practice.

thank you for stepping in explaining the matter in your own words.

You are very welcome.

, because I think it is better to have rather less collision potential in the far future than such a high risk potential of collisions forever.

Yeah, I agree. I didn’t add the $PREFIX variable myself, it exists since termux was created in 2015, I only took over development around 2 years ago, but any new variables that I add now are all scoped to $TERMUX__ or $TERMUX_APP__, etc, to prevent this kinda situation. Softwares should always use scoped variables, easier to understand code too.

but you’d have to update unmaintained decade-old versions of it, since the latest npm is not compatible with older node versions in my experience.

Termux only provides latest and LTS node, so using latest npm and latest/LTS node should work just fine. Old versions get removed from our repos and mirrors due to space issues and shared lib linking issues against old dependencies. There are user hosted repos that provide old versions, but everyone knows that all fixes don’t get backported and often updated versions must be used for fixes.

https://github.com/termux/termux-packages/tree/master/packages/nodejs

https://github.com/termux/termux-packages/tree/master/packages/nodejs-lts

For a patch, currently npm uses checks like following in different places

https://github.com/npm/libnpmconfig/blob/e9b201772fc461dd66b0b65a768e1f888273c302/index.js#L94

function getGlobalPrefix () {
  if (process.env.PREFIX) {
    return process.env.PREFIX
  } else if (process.platform === 'win32') {
    // c:\node\node.exe --> prefix=c:\node\
    return path.dirname(process.execPath)
  } else {
    // /usr/local/bin/node --> prefix=/usr/local
    let pref = path.dirname(path.dirname(process.execPath))
    // destdir only is respected on Unix
    if (process.env.DESTDIR) {
      pref = path.join(process.env.DESTDIR, pref)
    }
    return pref
  }
}

And it can use

function getGlobalPrefix () {
  if (process.env.NPM_PREFIX) {
    return process.env.NPM_PREFIX
  } else if (process.env.PREFIX && process.env.NPM_IGNORE_LEGACY_PREFIX != "1") {
    return process.env.PREFIX
  } else if (process.platform === 'win32') {
...

Then termux and other $PREFIX conflicted platforms can always export NPM_IGNORE_LEGACY_PREFIX=1 and optionally export $NPM_PREFIX if they need custom prefix.

@agnostic-apollo first of all, thank you for stepping in explaining the matter in your own words. I think that deprecating PREFIX and introducing TERMUX__PREFIX is still the way to go, regardless of other actions taken or not, because I think it is better to have rather less collision potential in the far future than such a high risk potential of collisions forever. The result could be that unsetting PREFIX could become a Termux property that will come with a risk to break old things, but given enough time the risk shall becomes low as third parties update their scripts. Unfortunately, accessing PREFIX cannot print any warning on stderr, so it’s really necessary to inform developers to update their scripts to use the new environment variable.

Patching npm would be great too, but you’d have to update unmaintained decade-old versions of it, since the latest npm is not compatible with older node versions in my experience. I have to agree with @ljharb’s statement about the numbers, but I can absolutely understand that these are not pleasant conclusions for maintaining Termux.

@ljharb I think changing this in Termux is still harder though. If I understand you correctly, npm just reads this variable and nvm provides it. Termux cannot change it easily, because there are far more scripts in the wild that rely on this variable. On the flip-side npm could just read a different variable and fallback to $PREFIX, if it is not found. Then you could simply set the new variable and things would not break.

I opened a discussion at npm about it.

unless termux’s PREFIX variable can work when pointed to the default location of npm root -g on whichever npm-managed node is active.

will never gonna happen, it points to the usr directory within the Termux files. It will break everything if it will be changed.

This is really a huge F for both parties. I was trying to give node and npm a scoped variable somehow, but even overriding the prefix explicitly was not leading to any direction. I’m not deep enough into their code to understand it (yet) and their documentation lacks clear information about the PREFIX variable, only the argument is documented.

I wasn’t sure about the “mistakes were made” statement from Ryan Dahl until I faced this limitation yesterday. Termux has blood on their hands as well, I mean, it could’ve been obvious that PREFIX could collide and that TERMUX_PREFIX would’ve been a smarter choice, but we are humans and human do errors.

Now running their nodejs-lts, so that the neovim-node-host can run at least, but it locks me away from testing some legacy stuff before porting it to LTS, which is quite a bummer.

@ljharb

In other words, if both Termux and node aren’t going to change, then Termux just isn’t compatible with using a node version manager. I’m still not clear on why Termux couldn’t change the name of their env var - is there an issue on their project I could read about it?

What a great suffering trying to get NVM and Termux work in harmony now, because of the “great” naming decisions that were made on Termux and Nodes end.

To answer your questions few years after:

PREFIX can’t be renamed in termux at this point. Termux packages including termux-tools, scripts of termux users, wikis, termux plugins, etc rely on it. Changing it would break a lot (understatement), so it’s not possible.

_Originally posted by @agnostic-apollo in https://github.com/termux/termux-app/issues/2096#issuecomment-851145727_

What I don’t get, though: If this cannot be fixed in NVM and Node is at fault, how is it that Node runs when installed from the Termux package manager?

Is there really nothing we can do about it?

What if I create aliases for npm and node in which I preset the proper PREFIX? What should the PREFIX actually be to get node and npm to work? I tried to launch node --prefix $NVM_DIR/versions/node/v.../ for test purposes, but no matter what I launch it with, I always get: bash: /data/data/com.termux/files/home/.nvm/versions/node/v.../bin/node: cannot execute: required file not found. I was able to get this far by doing PREFIX= nvm install 'lts/*'

@bradennapier Seems like Xcode launching Terminal from /usr/local, but your nvm has been installed and located in your user’s folder.

this is my solution

  1. Move the .nvm folder (user root directory) to the directory /usr/local
  2. update the location on your .zshrc or .bash_profile file
  3. restart your terminal

@ntelkedzhiev 's solution worked. Small grammar police thing to note, the command is brew uninstall yarn but I’m sure most of us figured that out 😃

Thank you @ntelkedzhiev !

@enmanuelduran if unsetting PREFIX doesn’t solve it, please file a new issue and fill out the entire template.

This is still an issue, I am having it on react-native on nvm version 0.38.o when trying to run my ios build.

FYI, I am having this issue with any regular MacOS terminal now. I am using react native as someone posted before and my PREFIX variable returns ‘/usr/local’. Not sure which tool is setting it now. @goodevilgenius workaround worked for me tho.

@goodevilgenius Now my resolution is installing a ubuntu using atilo:https://github.com/YadominJinta/atilo and then install nvm in ubuntu.

@ljharb Will do!

@bradennapier Seems like Xcode launching Terminal from /usr/local, but your nvm has been installed and located in your user’s folder.