How to fix npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node_modules' in npm
npm cannot write to the global prefix because it is root-owned or locked. Move globals into your home (nvm/user prefix) or realign ownership once, then reinstall cleanly.
Quick fix
Fixes npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node_modules'
npm config get prefix
ls -ld $(npm config get prefix)/{lib/node_modules,bin}- Inspect prefix and permissions
- Switch to nvm/fnm/asdf or a user prefix (preferred)
- Clean staging and cache
- Realign ownership once (if you administer the host)
npm config get prefixls -ld $(npm config get prefix)/{lib/node_modules,bin}npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node_modules'
What this error means
npm installs global packages into the prefix directory (default /usr/local/lib/node_modules) and links executables under prefix/bin. When those directories are owned by root or mounted read-only, a normal user cannot create or modify files, so npm aborts early with EACCES instead of leaving partially written packages. The issue appears when system Node was installed with sudo or a package manager, when prior sudo npm installs left root-owned artifacts, or when running inside Docker/CI as a non-root user against a root-owned filesystem. Windows/WSL users can also hit it if Defender or corporate EDR blocks writes to node_modules.
Typical symptoms
- npm install -g fails immediately with EACCES on /usr/local/lib/node_modules
- Command succeeds only with sudo/Admin privileges
- npm config get prefix returns /usr/local or another root-owned path
- Leftover .staging/.DELETE folders remain after failure
- Global binaries missing from PATH after install attempt
- In Docker/CI, non-root npm jobs fail while root works
Common causes
- System-wide Node install created root-owned prefix/bin directories
- Previous sudo npm installs left root-owned files blocking user writes
- Corporate or locked-down images mark /usr/local read-only to non-root users
- Homebrew or package-manager Node with drifted ownership in /usr/local or /opt/homebrew
- Docker/CI or WSL running npm as a non-owner of the mounted volume
- AV/EDR (Defender, CrowdStrike) holding locks on node_modules during install
How to fix "npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node_modules'"
npm config get prefix
ls -ld $(npm config get prefix)/{lib/node_modules,bin}Confirm whether the prefix and bin are root-owned or read-only.
# nvm example
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \ . "$NVM_DIR/nvm.sh"
nvm install --lts
# fallback user prefix
mkdir -p ~/.npm-global
npm config set prefix ~/.npm-global
export PATH="$HOME/.npm-global/bin:$PATH"Keep the PATH export in your shell profile so globals resolve.
sudo rm -rf $(npm config get prefix)/lib/node_modules/.staging $(npm config get prefix)/lib/node_modules/.*.DELETE 2>/dev/null || true
npm cache clean --forceRemoves root-owned temp folders that block retries.
sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}Do this only on machines you control; avoid on shared hosts.
npm install -g <package>Run with the user-owned prefix so npm can write normally.
If you see EPERM/EACCES on Windows paths, close VS Code/terminals that hold node_modules, add a Defender exclusion for your global prefix, and retry from an elevated PowerShell or with Developer Mode enabled for symlinks.
Advanced notes
In Docker/CI, either run npm as the image owner (often root) or set a user prefix inside the workspace volume to avoid root-owned /usr/local. On macOS Homebrew, ensure the brew user owns /usr/local or /opt/homebrew; permission drift there is common after OS upgrades. Avoid mixing sudo and user installs because it creates root-owned artifacts that keep failing future installs. Windows/WSL users should watch for Defender/EDR locks and enable Developer Mode to allow npm-created symlinks and temp files.
Frequently asked questions
- What does "npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node" mean?
- npm installs global packages into the prefix directory (default /usr/local/lib/node_modules) and links executables under prefix/bin. When those directories are owned by root or mounted read-only, a normal user cannot create or modify files, so npm aborts early with EACCES instead of leaving partially written packages. The issue appears when system Node was installed with sudo or a package manager, when prior sudo npm installs left root-owned artifacts, or when running inside Docker/CI as a non-root user against a root-owned filesystem.
- How do I fix "npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node"?
- npm cannot write to the global prefix because it is root-owned or locked. Move globals into your home (nvm/user prefix) or realign ownership once, then reinstall cleanly.
- What causes "npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node"?
- System-wide Node install created root-owned prefix/bin directories Previous sudo npm installs left root-owned files blocking user writes Corporate or locked-down images mark /usr/local read-only to non-root users
- Is the "npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node" error serious?
- It is a medium-severity error โ more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- ๐npm Official Documentation
- ๐npm Docs: Resolving EACCES for global installs(Official Docs)
- ๐ฌStack Overflow: EACCES installing globally(Stack Overflow)
- ๐