Skip to content

Instantly share code, notes, and snippets.

@rcugut
Forked from DanHerbert/fix-homebrew-npm.md
Last active February 2, 2024 11:51
Show Gist options
  • Save rcugut/c7abd2a425bb65da3c61d8341cd4b02d to your computer and use it in GitHub Desktop.
Save rcugut/c7abd2a425bb65da3c61d8341cd4b02d to your computer and use it in GitHub Desktop.
Install node & npm on Mac OS X with Homebrew

DEPRECATED as of macOS 10.13 (High Sierra). See the new GUIDE to install nvm and yarn for macOS (updated July 2019)

Fixing npm On Mac OS X for Homebrew Users

Installing node through Homebrew can cause problems with npm for globally installed packages. To fix it quickly, use the solution below. An explanation is also included at the end of this document.

Solution

This solution fixes the error caused by trying to run npm update npm -g. Once you're finished, you also won't need to use sudo to install npm modules globally.

Before you start, make a note of any globally installed npm packages. These instructions will have you remove all of those packages. After you're finished you'll need to re-install them.

Run the following commands to remove all existing global npm modules, uninstall node & npm, re-install node with the right defaults, install npm as its own pacakge, and configure the location for global npm modules to be installed.

1. Re-install node without npm

# run the following commands

# this next line erases all the existing global npm packages
rm -rf /usr/local/lib/node_modules

# remove previously installed node
brew uninstall node
brew prune # clean all broken symlinks
brew update # always good to have the latest

# install node via brew, but without npm
# there are 2 options:
# - if you want to use `yarn` (yarnpkg.com), you need latest 'node'
# - if you don't use `yarn` (yarnpkg.com), prefer LTS 'node@6'

brew install node --without-npm


# install yarn (see yarnpkg.com for more info)
brew install yarn
# follow up with: https://yarnpkg.com/en/docs/install

You should now be able to run the node command

2. Prepare the npm new home: /usr/local/npm_packages

# run the following commands

mkdir -p /usr/local/npm_packages


# ONLY IF THE COMMAND ABOVE FAILS >>>
# it means the permissions are wrong with your `/usr/local` folder, so fix it;
# normally, with Homebrew, your user should own the entire `/usr/local` folder:

sudo chown -R `whoami` /usr/local

Add/append the following lines in ~/.bashrc

# this is the root folder where all globally installed node packages will  go
export NPM_PACKAGES="/usr/local/npm_packages"
export NODE_PATH="$NPM_PACKAGES/lib/node_modules:$NODE_PATH"
# add to PATH
export PATH="$NPM_PACKAGES/bin:$PATH"

And make sure you load the .bashrc in your .bash_profile:

  • IMPORTANT: make sure you do not have both a .profile and a .bash_profile; if you do, copy everything from .profile into .bash_profile and then remove the .profile
  • Check if the following or similar line exists in your .bash_profile:
[[ -s ~/.bashrc ]] && source ~/.bashrc
  • make sure .bashrc is executable
# run the following commands

chmod +x ~/.bashrc

3. Restart your iTerm / Terminal

IMPORTANT: close all existing iTerm/Terminal sessions and re-open iTerm/Terminal before going further

Advanced: or just reload the .bash_profile -- source ~/.bash_profile

3. Install npm from npmjs.com

First, set the correct npm home in ~/.npmrc

Make sure ~/.npmrc file exists, and contains a line as below:

prefix=/usr/local/npm_packages

Run the npm install script from npmjs.com

curl -L https://www.npmjs.com/install.sh | sh

NOTE @ July 13 2017: the install script from above (from npmjs.com) silently fails and doesn't copy the npm package contents correctly (see comments below from @hughsw). In order to (hack)fix this you can do the following after running the above npm install.sh script.

The instructions below apply to npm 5.2.0, but may work for earlier or later 5.x releases:

# manually download and un-targz into a local dir (it will be named `package`)
curl -L https://registry.npmjs.org/npm/-/npm-5.2.0.tgz | tar xz

# remove the broken npm symlink (generated by the nppmjs install.sh script)
rm -rf /usr/local/npm_packages/lib/node_modules/npm

# move the extracted `package` in the correct place and rename to `npm`
mv package /usr/local/npm_packages/lib/node_modules/npm

# that should do it. The bin/npm symlinks should now work

# make sure it works, and update to latest available npm:
npm install -g npm

# if you reach this step, w/o any errors =>  ALL OK!

That's it. You should now be able to run the npm command without sudo.


NEVER run npm as sudo; so never do sudo npm install ...


Explanation of the issue

If you're a Homebrew user and you installed node via Homebrew, there is a major philosophical issue with the way Homebrew and NPM work together. If you install node with Homebrew and then try to do npm update npm -g, you may see an error like this:

$ npm update npm -g
npm http GET https://registry.npmjs.org/npm
npm http 304 https://registry.npmjs.org/npm
npm http GET https://registry.npmjs.org/npm/1.4.4
npm http 304 https://registry.npmjs.org/npm/1.4.4
npm ERR! error rolling back Error: Refusing to delete: /usr/local/bin/npm not in /usr/local/lib/node_modules/npm
npm ERR! error rolling back     at clobberFail (/usr/local/Cellar/node/0.10.26/lib/node_modules/npm/lib/utils/gently-rm.js:57:12)
npm ERR! error rolling back     at next (/usr/local/Cellar/node/0.10.26/lib/node_modules/npm/lib/utils/gently-rm.js:43:14)
npm ERR! error rolling back     at /usr/local/Cellar/node/0.10.26/lib/node_modules/npm/lib/utils/gently-rm.js:52:12
npm ERR! error rolling back     at Object.oncomplete (fs.js:107:15)
npm ERR! error rolling back  [email protected] { [Error: Refusing to delete: /usr/local/bin/npm not in /usr/local/lib/node_modules/npm] code: 'EEXIST', path: '/usr/local/bin/npm' }
npm ERR! Refusing to delete: /usr/local/bin/npm not in /usr/local/lib/node_modules/npm
File exists: /usr/local/bin/npm
Move it away, and try again. 

npm ERR! System Darwin 13.1.0
npm ERR! command "/usr/local/Cellar/node/0.10.26/bin/node" "/usr/local/bin/npm" "update" "npm" "-g"
npm ERR! cwd /Users/dan/Google Drive/Projects/dotfiles
npm ERR! node -v v0.10.26
npm ERR! npm -v 1.4.3
npm ERR! path /usr/local/bin/npm
npm ERR! code EEXIST
npm ERR! 
npm ERR! Additional logging details can be found in:
npm ERR!     /Users/dan/Google Drive/Projects/dotfiles/npm-debug.log
npm ERR! not ok code 0

There's an NPM bug for this exact problem. The bug has been "fixed" by Homebrew installing npm in a way that allows it to manage itself once the install is complete. However, this is error-prone and still seems to cause problems for some people. The root of the the issue is really that npm is its own package manager and it is therefore better to have npm manage itself and its packages completely on its own instead of letting Homebrew do it.

Also, using the Homebrew installation of npm will require you to use sudo when installing global packages. Since one of the core ideas behind Homebrew is that apps can be installed without giving them root access, this is a bad idea.

@MirelesCloud
Copy link

You're my hero. I've spent all day trying to get npm working. This finally worked. However, note that this step # move the extracted package in the correct place and rename to npm
mv package /usr/local/npm_packages/lib/node_modules/npm
turned out the following error
mv: rename package to /usr/local/npm_packages/lib/node_modules/npm: No such file or directory
I haven't been able to fix this.

@vukanac
Copy link

vukanac commented Apr 5, 2018

List and save if you need all previous packages (won't work if you have already removed node):

$ npm list -g

Remove global packages:
$ rm -rf /usr/local/lib/node_modules
$ rm -rf ~/.npm-packages/lib/node_modules/npm

Then just install node (latest) (with npm) with brew:
$ brew install node
$ node -v
$ npm -v // eg. 5.6.0

Test does it work without sudo:
$ npm install -g npm
$ npm -v // eg. 5.8.0

@w4-hojin
Copy link

w4-hojin commented Jun 12, 2018

Now, node LST is @8.
Even if we use node LTS, we can use yarn also.

@edPratt
Copy link

edPratt commented Mar 12, 2019

Since --without is deprecated, this no longer works. this worked for me

@idelendik
Copy link

brew prune has been replaced. Call brew cleanup instead.
Homebrew version: 2.2.2.

@idelendik
Copy link

brew install node --without-npm returns invalid option: --without-npm

Options have been removed from formula last year. brew install node is the way to get node and you’ll get npm with that. If you don’t want npm you could maintain a separate version of the node formula for yourself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment