Executive Summary & Root Cause Analysis: The error
npm ERR! code EACCES(syscall open/mkdir/access,permission denied) occurs when runningnpm install -g <package>on macOS or Linux. By default, system-wide Node.js installations place global packages inside root-owned directories such as/usr/local/lib/node_modulesor/usr/lib/node_modules. Because standard user accounts lack write permissions to these system paths, npm aborts the installation. Common triggers include: (1) installing Node.js via official OS installers or system package managers (APT/DNF) rather than a user-space version manager, (2) previously runningsudo npm install, which leaves root-owned files inside your local~/.npmcache, and (3) restrictive permissions on CI/CD or shared build servers.
Step 1: Recommended Fix – Reinstall Node.js Using a Version Manager (NVM)
The official npm-recommended long-term solution is managing Node.js through a Node Version Manager (such as nvm on Linux/macOS or nvm-windows on Windows). Version managers install Node.js and all global packages directly inside your user home directory, eliminating system permission conflicts completely.
# Install NVM (Linux / macOS)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
# Reload your shell configuration (Bash or Zsh)
source ~/.bashrc # or: source ~/.zshrc
# Install and activate the latest LTS release of Node.js
nvm install --lts
nvm use --lts
# Install your global package without sudo
npm install -g <package-name>
Step 2: Configure a User-Owned Global Directory for npm
If you prefer to keep your existing system-wide Node.js installation without switching to NVM, reconfigure npm’s global prefix to point to a hidden folder inside your home directory:
# 1. Create a directory for global npm installations
mkdir -p ~/.npm-global
# 2. Configure npm to use the new directory path
npm config set prefix '~/.npm-global'
# 3. Add the new global bin path to your shell profile (~/.bashrc, ~/.zshrc, or ~/.profile)
echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.profile
# 4. Reload your shell profile
source ~/.profile
# 5. Test global installation cleanly
npm install -g <package-name>
Step 3: Alternative Workarounds – Cache Ownership & npx
If the EACCES error occurs during a local npm install (not global) or inside ~/.npm, or if you only need to run a CLI tool once:
- Repair ownership of your local npm cache and node_modules:
# Fix root-owned files left behind by prior 'sudo npm' commands sudo chown -R $(whoami):$(id -gn) ~/.npm sudo chown -R $(whoami):$(id -gn) ./node_modules - Use
npxto run CLI tools without global installation:# Execute CLI packages directly without modifying global directories npx <package-name> <arguments>
Verification & Testing Steps
Confirm that npm resolves global installations to a user-writable path and executes installed binaries without permission errors:
# Verify the active npm global prefix points to your home directory
npm config get prefix
# Confirm where global binaries are resolved in PATH
which <installed-cli-command>
# Run a test global install and check package list
npm list -g --depth=0
Summary Comparison Table
| Resolution Method | How It Works | Security & Stability | Best Used For |
|---|---|---|---|
Node Version Manager (nvm) |
Installs Node & global packages in user home dir | Highest (Zero sudo needed, easy version switching) |
Local development machines |
Custom npm prefix (~/.npm-global) |
Redirects global package path to user directory | High (Preserves system Node binary) | Servers or locked-down environments |
sudo chown -R on ~/.npm |
Fixes ownership of corrupted cache/local folders | High (Repairs prior sudo npm damage) |
Local npm install cache errors |
npx <package> |
Downloads & runs CLI tools ephemerally | Highest (No global state modified) | One-off scaffolding & build scripts |
Leave a Reply