MacOS Permission Denied Error When Installing NPM Packages

I keep running into permission issues when trying to install npm packages on my Mac running Sequoia 15.4. Every time I try to run the installation, I get this error:

npm ERR! code EACCES
npm ERR! syscall mkdir
npm ERR! path /usr/local/lib/node_modules/express
npm ERR! dest /usr/local/lib/node_modules/.express-temp123
npm ERR! errno -13
npm ERR! Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules/express' -> '/usr/local/lib/node_modules/.express-temp123'
npm ERR!     at async Object.mkdir (node:internal/fs/promises:654:8)
npm ERR!     at async createDirectory (/usr/local/lib/node_modules/npm/node_modules/@npmcli/fs/lib/create-dir.js:25:3)
npm ERR!     at async Promise.allSettled (index 1)
npm ERR!     at async [installPackages] (/usr/local/lib/node_modules/npm/node_modules/@npmcli/arborist/lib/arborist/install.js:298:9)
npm ERR!     at async Arborist.install (/usr/local/lib/node_modules/npm/node_modules/@npmcli/arborist/lib/arborist/install.js:125:3)
npm ERR!     at async Install.execute (/usr/local/lib/node_modules/npm/lib/commands/install.js:135:4)
npm ERR!     at async Npm.execute (/usr/local/lib/node_modules/npm/lib/npm.js:198:7)
npm ERR!     at async main (/usr/local/lib/node_modules/npm/lib/cli/main.js:65:3) {
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'mkdir',
npm ERR!   path: '/usr/local/lib/node_modules/express',
npm ERR!   dest: '/usr/local/lib/node_modules/.express-temp123'
npm ERR! }
npm ERR!
npm ERR! Your system rejected this operation.
npm ERR! You probably don't have permission to write to this directory as your current user
npm ERR!
npm ERR! If you think this is a permission problem, check the file permissions
npm ERR! and folder permissions, or try running with sudo/Administrator privileges.
npm ERR! Full log available at: /Users/johndoe/.npm/_logs/2025-04-23T01_15_32_458Z-debug-0.log

I looked up some solutions online and tried a few different approaches. I attempted to reinstall npm using a node version manager and also tried using Homebrew to fix the issue. When I tried to modify the default npm directory, the terminal said “command not found” so that didn’t work either. Has anyone else dealt with this kind of permission problem on MacOS?

Same exact issue when I upgraded to Sequoia! The newer macOS versions are way stricter about system directories. Don’t bother fighting permissions or using sudo - it’ll just mess up your npm cache.

Here’s what works: change your npm prefix to a directory you actually own. Run mkdir ~/.npm-global then npm config set prefix '~/.npm-global'. Add export PATH=~/.npm-global/bin:$PATH to your .zshrc or .bash_profile. Restart your terminal and you’re good to go.

This way you keep your system Node untouched but get a safe spot for global packages. I’ve been running this setup for eight months - zero issues.

This permission error drove me crazy for months until I figured out the real problem - how I installed Node. That /usr/local/lib/node_modules path means you probably used the official installer from nodejs.org, which creates ownership conflicts on macOS. I fixed it permanently by ditching my Node installation and switching to nvm. First, completely remove your current Node - check /usr/local/bin for any node/npm binaries and delete them. Then grab nvm with the curl command from their GitHub page. After that, run nvm install node for the latest version. This installs Node in your user directory instead of system directories, so no more permission headaches. I’ve used this setup for over two years - zero EACCES errors. Don’t use sudo with npm either, it just creates more problems later. nvm is cleaner and you get version management too.

The Problem:

You’re encountering permission errors when installing npm packages on your macOS system (Sequoia 15.4), resulting in an EACCES error. This indicates that your user account lacks the necessary permissions to write to the system’s default npm directory (/usr/local/lib/node_modules). Attempts to use sudo or modify system directories are discouraged due to potential security risks and system instability. You’ve also explored reinstalling npm and using Homebrew, but these haven’t resolved the core issue.

:thinking: Understanding the “Why” (The Root Cause):

The root cause is likely a conflict between the location where Node.js and npm are installed and the permissions associated with that location. Installing Node.js using the official installer often places files in system directories that your user account doesn’t have write access to. This results in permission errors when npm tries to install packages into these protected locations. Using sudo might temporarily fix the issue, but it’s a risky workaround that creates security vulnerabilities and can lead to further complications in the long run.

:gear: Step-by-Step Guide:

This guide addresses the permission issue by installing Node.js and npm using Node Version Manager (nvm), which places the installation within your user directory, resolving permission problems.

  1. Install Node Version Manager (nvm): Download and install nvm following the instructions on the official nvm GitHub page. This will typically involve running a curl command. (Note that you must open a new terminal window after installing nvm for the changes to take effect).

  2. Install Node.js using nvm: Once nvm is installed, open a new terminal window. Use nvm to install a Node.js version: nvm install node. This will install Node.js and npm into your home directory, avoiding the permission issues associated with system directories.

  3. Verify the Installation: After installation, run node -v and npm -v to verify that Node.js and npm are installed correctly and that they are accessible from your terminal. The output should display the version numbers for both.

  4. Test npm installation: Now attempt to install a test package using npm. For example: npm install express. This command will install the express package into your user directory, avoiding the previously problematic system location.

  5. Optional: Setting up a Global npm Directory (Recommended): While not strictly necessary, it’s good practice to explicitly configure a global npm directory within your user space. This keeps your global packages separate and organized:

    • Create a global npm directory: mkdir ~/.npm-global
    • Set the prefix: npm config set prefix ~/.npm-global
    • Update your PATH environment variable: Add the following line to your .bashrc, .zshrc, or equivalent shell configuration file, ensuring that the path reflects the location you chose above: export PATH="$PATH:~/.npm-global/bin". Save the file, then source it using source ~/.zshrc (or the appropriate command for your shell).

:mag: Common Pitfalls & What to Check Next:

  • nvm Installation Issues: If you encounter problems during nvm installation, double-check that you followed the instructions carefully and that you opened a new terminal window after the installation. Verify that the nvm command is correctly added to your shell’s PATH environment variable.
  • Conflicting Node.js Installations: Ensure that you’ve completely removed any previous Node.js installations from your system before installing with nvm. Use which node and which npm to confirm there aren’t any conflicting installations.
  • Shell Configuration: Ensure you’ve correctly configured your shell’s .bashrc, .zshrc (or equivalent) file and sourced it after making changes to the PATH environment variable. If you used a different shell (e.g. fish), look at their configuration documentation for the appropriate syntax.

:speech_balloon: Still running into issues? Share your (sanitized) config files, the exact command you ran, and any other relevant details. The community is here to help!

You might have multiple Node installations fighting each other. This killed me when I had Homebrew and the official installer running at the same time. Run which node and which npm to see what paths you’re using. If they don’t match or point to different sources, that’s the problem. I had to nuke everything first with brew uninstall node npm, then manually delete /usr/local/lib/node_modules before doing a clean reinstall with just Homebrew. Only use one Node installation method. Mixed installations cause permission hell because different installers handle ownership differently. After wiping everything, brew install node gave me a setup that actually works with macOS permissions.

Had this exact problem after a fresh macOS install last year. Node’s official installer puts everything in /usr/local/lib/node_modules with root ownership, while Homebrew handles directory ownership differently - that’s what’s causing your error. I fixed it without reinstalling anything. Run sudo chown -R $(whoami) /usr/local/lib/node_modules /usr/local/bin /usr/local/share to take ownership of those directories. Then npm cache clean --force to clear corrupted cache files. Your npm installs should work normally without sudo after that. You’ll keep your current Node version and all global packages while permanently solving the permission problem. Been using this fix for over a year through multiple macOS updates - no issues.

honestly just use npm install --prefix ~/my-packages for global stuff instead of fighting system perms. been doing this for ages and never had issues. way simpler than changing configs or reinstalling everything imo

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.