Fix: npm ERR! EACCES permission denied
npm cannot write to a directory it needs: the global install location, its cache in ~/.npm, or a node_modules owned by root. Fix the ownership or install globals into a user-owned prefix instead of using sudo.
Drafted with AI from official documentation. Scripts were run in a test environment and repository links verified. Awaiting a human check. Did it work for you? Last edited Outdated?
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 ERR!
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.
EACCES is the operating system saying that the user running npm has no permission to create or change a file at the path shown. Read the path line: it tells you which of the three usual directories is the problem.
Cause 1: installing a global package into a root-owned prefix
On Linux and on Macs where Node came from an installer, globals go to /usr/local/lib/node_modules or /usr/lib/node_modules, which only root can write. npm’s own documentation recommends either a version manager, which installs Node into your home directory, or changing npm’s prefix to a folder you own. Do not use sudo npm install -g; it creates root-owned files that cause this very error later.
Check before you run this
- Downloads a file and runs it straight away. Open the URL and read the script first.
- Runs with administrator rights. Make sure you understand every line.
# Option A (recommended): a Node version manager such as nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
# open a new terminal, then
nvm install --lts
npm install -g typescript # now lands in ~/.nvm, no sudo
# Option B: keep your Node, move the global prefix into your home
mkdir -p ~/.npm-global
npm config set prefix ~/.npm-global
echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> ~/.bashrc # or ~/.zshrc
source ~/.bashrc
npm install -g typescript
Check the exact nvm version and URL on the nvm README before running the installer; piping a script to bash is only acceptable from a source you have verified.
Cause 2: root-owned files in the npm cache
If sudo npm was ever used, ~/.npm may contain files owned by root and every later install fails while writing the cache. npm prints the fix in the error itself: give the cache back to your user.
Check before you run this
- Runs with administrator rights. Make sure you understand every line.
sudo chown -R "$(id -u):$(id -g)" ~/.npm
npm cache verify
Cause 3: node_modules or the project folder is owned by someone else
A project cloned or built with sudo, copied from another user, or created inside a Docker volume can leave node_modules or package-lock.json owned by root. Fix the ownership of the project, not of the system.
Check before you run this
- Runs with administrator rights. Make sure you understand every line.
ls -ld . node_modules package-lock.json
sudo chown -R "$(id -u):$(id -g)" .
npm install
Careful: run that chown -R only inside your project directory. Running it on /, /usr or your whole home with the wrong user breaks the system.
Cause 4: a read-only or noexec location
Installing into a mounted network share, a read-only Docker layer, or a CI cache directory you do not own also gives EACCES. Build in a writable path (WORKDIR /app owned by the user in your Dockerfile; USER node after chown) or set npm_config_cache to a writable directory in CI.
Check that it is fixed
Check before you run this
- Runs with administrator rights. Make sure you understand every line.
npm config get prefix # a directory you own
npm install -g npm@latest # a global install that needs no sudo
npm ls -g --depth=0
When it is not what you think
EACCES: permission denied, open '/path/.env'at runtime is your application failing to read a file, not npm.EPERM: operation not permittedon macOS and Windows is a different code: a file is locked by another process or blocked by antivirus or by macOS privacy settings on folders such as Documents.ENOENTmeans a file is missing, often becausenpm installwas run in the wrong directory.EACCESwhen starting your app on port 80 or 443 is the kernel refusing a privileged port, nothing to do with npm; use a port above 1023 or a reverse proxy.
Official documentation
Did this work for you?
No votes yet. Be the first.
If it did not work, the report form below tells the editors what went wrong.
See also
- 0021 Read and write files in Node.js with fs/promises A complete Node script that walks a folder, reads text files, and writes a JSON report safely, showing the everyday fs/promises calls… Beginner · Step by step · Any system Script Node.js 15 Oct 2026
- 0022 Build a small Node.js CLI with util.parseArgs A complete, dependency-free command-line tool in Node: options and flags with parseArgs, input from files or a pipe, help text, and meaningful… Intermediate · Step by step · Any system Script Node.js 15 Oct 2026
- 0026 Fix: TypeError: Cannot read properties of undefined (reading ‘x’) You tried to read a property from a value that is undefined or null. Find which value is missing, then guard it… Beginner · Fixes an error · Any system Article Basics · Common errors 15 Oct 2026
- 0027 Fix: SyntaxError: Cannot use import statement outside a module The file uses ES module import syntax, but Node or the browser is loading it as a classic script or CommonJS. Tell… Intermediate · Fixes an error · Any system Article Common errors · Node.js 15 Oct 2026
- 0088 Fix: Access to fetch at ‘…’ from origin ‘…’ has been blocked by CORS policy The browser refused to give your script a cross-origin response because the server did not send the right Access-Control-* headers. Fix it… Intermediate · Fixes an error · Browser Article Common errors · Making requests 15 Oct 2026
- 0263 Build a notes REST API with plain Node.js: CRUD, validation, status codes and CORS Write a small JSON API for notes using only Node.js built-ins: create, read, update and delete, input validation, correct HTTP status codes,… Intermediate · Guided project · Any system Article Making requests · Node.js · Status codes 15 Oct 2026
Repos in the wild
- Node.js nodejs/node The source of the Node.js runtime: a JavaScript engine (V8) plus APIs for files, networking, processes and more, used to run JavaScript outside the browser. GitHub
- Express (expressjs/express) expressjs/express A minimal and flexible web framework for Node.js, built around routes and middleware, and the foundation of countless APIs and other frameworks. GitHub
History
Every saved edit is kept. The plot on the sleeve draws one line per edit. Open any edit to see exactly what changed.
- Dominik +3,792 chars