Coding Agents & Terminal · recorded 2026-08-29 · applies to 1 tool(s) ✓ Verified

Problem: npm install -g fails with EACCES (two forms, two fixes) —— Trove problem library

Verified 2026-08-29npm install -g EACCES — move the global prefix to your user dir (`npm config set prefix ~/.npm-global`) for a permanent fix.

Quick fix

# One-liner (form 1, recommended): move the global prefix to your user directory, permanent fix
npm config set prefix ~/.npm-global && export PATH="$HOME/.npm-global/bin:$PATH" && npm install -g <pkg>

For form 2: sudo chown -R $(whoami) ~/.npm.

What you will run into

npm install -g <pkg> reports npm ERR! code EACCES; you think "permission issue, add sudo" — and next time even the cache can't be written (Your cache folder contains root-owned files), making it worse.

The error actually has two forms with different paths and completely different fixes — check where path points before acting.

Why this happens

npm global installs write to two locations: the global package directory (npm prefix -g, e.g. /usr/local/lib/node_modules) and the cache (~/.npm):

Formpath points toRoot cause
Form 1/usr/local/lib/node_modules/...Global dir owned by root, current user isn't root
Form 2/home/<user>/.npm/_cacacheUsed sudo npm install before; ~/.npm got mixed with root-owned files

Form 1 is the norm for non-root users installing global packages (system node lives in /usr/local or /usr); form 2 is the after-effect of having used sudo before. Both errors carry EACCES + errno -13, but the fixes differ.

Global npm installs write to two locations: the global package directory (node_modules under npm prefix -g) and the cache (~/.npm).

EACCES means "the current user cannot write to the target directory": form 1's global directory is owned by root (system node lives in /usr/local or /usr), so non-root writes are rejected;

form 2 comes from a historical sudo npm install that made root the owner of ~/.npm cache files, after which normal-user cache writes fail.

Both forms show EACCES/errno -13, but the causes and fixes differ completely — form 1 is "directory ownership", form 2 is "cache ownership poisoned".

Deterministic takeaway: an error path containing node_modules = form 1; containing _cacache/.npm = form 2;

the correct fix for form 1 is npm config set prefix ~/.npm-global (move the global dir into the user home and add to PATH — do not force-install with sudo), and for form 2 sudo chown -R $(whoami) ~/.npm (restore cache ownership);

fixed diagnostic: ls -ld the target directory and compare with the error path.

Step by step

1. Read the error's path to identify the form — Diagnose

npm install -g yaml 2>&1 | grep -E "path|EACCES"

path /usr/local/lib/... → form 1; path /home/<user>/.npm/_cacache → form 2.

2. Form 1: move the global prefix to your user directory (recommended) — Required

npm config set prefix ~/.npm-global
export PATH="$HOME/.npm-global/bin:$PATH"

Add export PATH=... to ~/.bashrc so global packages install into your own directory from now on, never touching system dirs.

3. Form 2: give ~/.npm back to yourself — Required

sudo chown -R $(whoami) ~/.npm

npm's error message usually suggests the matching chown command. If you don't care about old cache, rm -rf ~/.npm and let it rebuild.

4. Alternatives — Advanced

  • Manage node with nvm: node lives under ~/.nvm, global packages are naturally writable;
  • sudo npm install -g works but isn't recommended — it keeps manufacturing form 2.

How to confirm it works

npm install -g yaml && yaml --help

No more EACCES and yaml runs (prints usage) means success. Measured: after form-1 fix added 1 package; after form-2 chown changed 1 package.

Other environments

EnvironmentNotes
Linux (system node in /usr/local)Form 1 common; move prefix to ~/.npm-global
WSL UbuntuSame as native Linux; leftover sudo also manufactures form 2
macOS (Homebrew node)Dir owned by brew user; nvm or prefix change recommended too
Used sudo beforeAlways check ~/.npm ownership; chown -R $(whoami) ~/.npm

Symptom

npm install -g <pkg> fails with a permission error, in two typical forms:

# Form 1: no write permission on the global package dir (most common)
npm ERR! code EACCES
npm ERR! syscall mkdir
npm ERR! path /usr/local/lib/node_modules/yaml
npm ERR! Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules/yaml'

# Form 2: cache dir owned by root (after using sudo)
npm ERR! code EACCES
npm ERR! syscall mkdir
npm ERR! path /home/<user>/.npm/_cacache
npm ERR! Your cache folder contains root-owned files, due to a bug in
npm ERR! previous versions of npm which has since been addressed.

Key traits: both forms carry npm ERR! code EACCES + errno -13; exit code is usually 243; Form 1 happens for non-root users installing globally (system node under /usr/local or /usr, dirs owned by root); Form 2 is common after ever running sudo npm install (root-owned files mixed into ~/.npm, regular users can no longer write).

Cause

Global installs write two locations: the global package dir (npm prefix -g, e.g. /usr/local/lib/node_modules) and the cache (~/.npm). The former is root-owned while your user isn't root → Form 1; the latter got root-owned files/dirs (sudo leftovers) → Form 2. Same EACCES, different paths, different fixes — check what path says first.

Solution

  1. Form 1: move the global prefix into your home (recommended, one-time):
   npm config set prefix ~/.npm-global
   export PATH="$HOME/.npm-global/bin:$PATH"   # add to ~/.bashrc

Global installs now go to your own directory and never touch system dirs.

  1. Form 1 alternatives: manage node with nvm (node lives in ~/.nvm, global dirs are naturally writable); or sudo npm install -g (works but not recommended — it creates Form 2).
  2. Form 2: give ~/.npm back to yourself:
   sudo chown -R $(whoami) ~/.npm

(npm's own error suggests the exact chown command.) If you don't need the old cache, rm -rf ~/.npm and let it rebuild.

  1. Verify: npm install -g <pkg> succeeds and the command runs (e.g. yaml prints usage).
Verification Evidence
  • Local repro (2026-08-29, WSL Ubuntu, node v22.22.1 / npm 9.2.0, global prefix /usr/local; temporary user <user>):
  • Form 1 repro: <user> runs npm install -g yaml → EACCES: permission denied, mkdir '/usr/local/lib/node_modules/yaml' (exit 243);
  • Form 1 fix: npm config set prefix ~/.npm-global + PATH → same command added 1 package, yaml runs (usage output);
  • Form 2 repro: chown /home/<user>/.npm to root → install again → EACCES ... /home/<user>/.npm/_cacache, npm itself suggests sudo chown -R 1002:1002 "/home/<user>/.npm" (exit 243);
  • Form 2 fix: chown -R <user>:<user> /home/<user>/.npm → changed 1 package success;
  • Temporary user and cache removed afterwards (no leftovers in the test environment).

Evidence details kept locally (2026-08-29)

Applicable tools (1)

This problem is linked from the tool pages below — reachable from either side.

npm

Bundled solutions (combos)

This problem is part of the following verified bundles.

Source & evidence

Recorded Verified ✓ VerifiedApplies to 1 tool(s)
Entries contain locally measured or reviewable-source solutions; unmeasured items are explicitly labeled.

Source: https://github.com/vuejs/vue-cli/issues/1809

← Coding Agents & Terminal domain | Problem Catalog Experience | Facing another issue? Go to the Helpdesk