Ffile2fix
Sign in Get started

Fix npm "EACCES: permission denied"

npm ERR! code EACCES
npm ERR! syscall mkdir
npm ERR! path /usr/local/lib/node_modules/typescript
npm ERR! errno -13
npm ERR! Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules/typescript'

npm tried to write to a folder your user does not own: the system-wide global folder, a cache made root-owned by an earlier sudo command, or a project's node_modules. The fix is to give npm a folder you own, not to run npm with sudo.

Also appears as: npm error code EACCES npm error Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules/pnpm' · npm ERR! Error: EACCES: permission denied, rename '/home/user/.npm/_cacache/tmp/...' · Error: EACCES: permission denied, open '/home/user/project/node_modules/.package-lock.json' · npm ERR! Your cache folder contains root-owned files, due to a bug in previous versions of npm which has since been addressed.

Common causes

  • Global installs (npm install -g) into /usr/local/lib/node_modules, which belongs to root when Node came from a system package or installer
  • An earlier sudo npm command left root-owned files in ~/.npm
  • node_modules or package-lock.json in the project was created by sudo npm install or inside a Docker container as root
  • The project folder is on a mount or share where your user lacks write permission
  • Running npm in CI or Docker as a non-root user against files copied in as root

How to fix it

  1. Fix a root-owned cache. If the path is under ~/.npm, run sudo chown -R $(id -u):$(id -g) ~/.npm. This is the fix npm itself suggests for 'Your cache folder contains root-owned files'.
  2. Fix the project folder. If the path is inside your project, run sudo chown -R $(id -u):$(id -g) node_modules package-lock.json, or delete node_modules and reinstall with plain npm install.
  3. Install Node with a version manager. Install nvm (or fnm/Volta) and run nvm install --lts. Node and its global packages then live in your home folder, so npm install -g never needs sudo.
  4. Or set a user-owned global prefix. Run mkdir -p ~/.npm-global and npm config set prefix ~/.npm-global, then add export PATH=~/.npm-global/bin:$PATH to ~/.bashrc or ~/.zshrc and open a new shell.
  5. Use the right user in Docker. Set USER node before npm install in the Dockerfile and copy files with COPY --chown=node:node . . so the container user owns the app folder.

Terminal

# root-owned cache
sudo chown -R $(id -u):$(id -g) ~/.npm

# user-owned global folder (alternative to nvm)
mkdir -p ~/.npm-global
npm config set prefix ~/.npm-global
echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

How to stop it happening again

  • Never run sudo npm install, globally or in a project
  • Manage Node with nvm, fnm or Volta on developer machines
  • Use npx for one-off CLIs instead of installing them globally
  • Run containers and CI jobs as the same user that owns the files

Frequently asked questions

Why not just use sudo?

sudo runs package install scripts as root and leaves root-owned files behind, which causes the next EACCES error. A user-owned Node install avoids both problems.

Does this happen on Windows?

Less often, but yes: a file locked by an editor or antivirus, or a project in a protected folder like Program Files, can cause EACCES or EPERM. Close programs using the folder or move the project to your user directory.

Should I chmod 777 the folder?

No. Making folders world-writable is a security risk. Changing the owner to your user with chown is the correct fix.