← Back to DevBytes

Fix 'npm ERR! code EACCES' Permission Error

Understanding the EACCES Permission Error in npm

When you run an npm command such as npm install, npm update, or npm start and see a wall of red text ending with npm ERR! code EACCES, you've encountered one of the most common Node.js development hurdles. The EACCES error (short for "Error Access") indicates that npm does not have sufficient filesystem permissions to perform the requested operation. This typically happens when npm tries to write to directories owned by the root user while running as a regular user account.

Here's what a typical EACCES error looks like in your terminal:

npm ERR! code EACCES
npm ERR! syscall mkdir
npm ERR! path /usr/local/lib/node_modules
npm ERR! errno -13
npm ERR! Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules'
npm ERR!  [Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules'] {
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'mkdir',
npm ERR!   path: '/usr/local/lib/node_modules'
npm ERR! }
npm ERR! 
npm ERR! The operation was rejected by your operating system.
npm ERR! It is likely you do not have the permissions to access this file/directory.

The errno: -13 maps to the system error EACCES, confirming that the operating system denied the write operation. The syscall field tells you which system call failed — common ones include mkdir, open, unlink, and rename.

Why This Error Occurs

The root cause almost always stems from how Node.js and npm were initially installed. There are several common scenarios that create the permission mismatch:

Why Fixing This Properly Matters

Beyond simply getting your install to work, resolving the EACCES error correctly has long-term implications for your development environment:

Method 1: Fix Permissions on Existing Directories (Quick Fix)

🚀 Deploy your AI agent in 10 minutes

Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.

Try it free →

If you want the fastest resolution and are comfortable adjusting ownership, you can reclaim the relevant directories for your user account. First, identify which directories npm uses:

# Check npm's configured directories
npm config list

The output shows paths for prefix, cache, and other settings. The typical culprits are:

To fix ownership on a standard Linux or macOS system, run these commands without sudo, but note that you will need sudo to change ownership of root-owned directories:

# Find your current user and group
whoami
# Output: your-username

# Fix ownership of global node_modules
sudo chown -R $(whoami):$(id -gn) /usr/local/lib/node_modules

# Fix ownership of global bin directory
sudo chown -R $(whoami):$(id -gn) /usr/local/bin

# Fix ownership of the npm cache (usually already owned by you, but check)
sudo chown -R $(whoami):$(id -gn) ~/.npm

After running these commands, verify the fix by installing a package globally:

npm install -g eslint
# Should complete without EACCES errors

If you still see the error, check for additional directories that might be affected. You can trace exactly which path npm is trying to access from the error message's path field and apply the same chown treatment.

Resetting Project-Level Permissions

For a specific project where node_modules has mixed ownership, the cleanest approach is often to delete and reinstall:

# Remove the corrupted node_modules directory
rm -rf node_modules

# Clear npm's local cache for this project
npm cache clean --force

# Reinstall dependencies as your normal user
npm install

If you cannot delete node_modules because root-owned files are nested inside, use sudo rm -rf node_modules first, then proceed with the normal user install.

Method 2: Use a Node Version Manager (Recommended)

The most robust long-term solution is to avoid system-level package installations entirely by using a Node.js version manager. Version managers install Node and npm into your home directory, where you have full permissions without ever needing sudo. This approach eliminates the EACCES problem at its source.

Installing nvm (Node Version Manager)

nvm is the most widely used version manager. It installs Node.js and npm into ~/.nvm, completely sidestepping system directories:

# Download and run the nvm install script
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash

# Or using wget
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash

After the script completes, restart your terminal or source your shell configuration:

# For bash users
source ~/.bashrc

# For zsh users
source ~/.zshrc

# Verify nvm is available
nvm --version

Now install Node.js through nvm. This places everything in your home directory:

# Install the latest LTS version of Node.js
nvm install --lts

# Use it
nvm use --lts

# Verify npm's global prefix is now in your home directory
npm config get prefix
# Output: /home/your-username/.nvm/versions/node/v20.18.0

With this setup, you can install global packages freely:

npm install -g typescript
# No sudo, no EACCES errors — ever

Alternative: Using fnm (Fast Node Manager)

If you prefer a faster, Rust-based alternative, fnm works similarly and keeps everything user-local:

# Install fnm via cargo or a package manager
curl -fsSL https://fnm.vercel.app/install | bash

# Reload your shell
source ~/.bashrc  # or ~/.zshrc

# Install Node.js
fnm install 20
fnm use 20

Removing the Old System-Wide Installation

Once you've switched to a version manager, you should remove the system-level Node.js to avoid accidentally invoking the old, permission-restricted binary:

# On Debian/Ubuntu
sudo apt purge nodejs npm
sudo apt autoremove

# On macOS (if installed via the official pkg)
# Remove the following directories manually:
sudo rm -rf /usr/local/lib/node_modules
sudo rm -rf /usr/local/bin/node
sudo rm -rf /usr/local/bin/npm

# Also check for leftover symlinks
ls -la /usr/local/bin | grep node

After removal, ensure your shell resolves node and npm to the version manager's installation:

which node
# Should show something like ~/.nvm/versions/node/v20.18.0/bin/node

which npm
# Should show the corresponding npm path in ~/.nvm

Method 3: Configure npm to Use a User-Level Prefix

If you cannot or prefer not to use a version manager, you can reconfigure npm to store global packages entirely within your home directory. This approach requires no system permission changes and works with your existing Node.js installation.

Create a directory for user-level global packages:

mkdir -p ~/.npm-global

Tell npm to use this directory as its prefix:

npm config set prefix ~/.npm-global

Now you need to add ~/.npm-global/bin to your PATH so that globally installed binaries are executable from anywhere. Add this line to your shell configuration file (~/.bashrc, ~/.zshrc, or ~/.profile):

export PATH="$HOME/.npm-global/bin:$PATH"

Reload your shell configuration:

source ~/.bashrc  # or ~/.zshrc

Test the setup by installing a global package:

npm install -g http-server
# Now http-server is available without sudo
http-server --help

Verify the installation path confirms everything lives in your home directory:

npm config get prefix
# Output: /home/your-username/.npm-global

This method is particularly useful on shared systems or CI environments where you want to isolate global packages without modifying system directories.

Method 4: Fixing the npm Cache Directory

Sometimes the EACCES error is specifically tied to the npm cache. The cache lives at ~/.npm and can become corrupted or gain incorrect permissions over time. You can completely reset it:

# Force-clean the entire cache
npm cache clean --force

# Verify cache integrity
npm cache verify

If the cache directory itself has root-owned files, remove it entirely and let npm recreate it on the next install:

# Backup and remove the corrupted cache
rm -rf ~/.npm

# Next npm install will recreate ~/.npm with correct permissions
npm install

You can also relocate the cache to a custom location if needed:

npm config set cache ~/.npm-cache-custom
# This creates a fresh cache directory owned by your user

Best Practices to Prevent EACCES Errors

npm doctor
# Checks: npm ping, node version, permissions, cache, and more

Debugging Persistent EACCES Errors

If you've tried the methods above and still see EACCES, use these diagnostic steps to pinpoint the exact issue:

# 1. Check which paths npm is using
npm config list --json

# 2. Check ownership of all relevant directories
ls -la $(npm config get prefix)/lib/node_modules
ls -la $(npm config get cache)
ls -la $(npm config get prefix)/bin

# 3. Run a verbose install to see every file access attempt
npm install --verbose 2>&1 | grep EACCES

# 4. Check for any npm configuration overrides
cat ~/.npmrc
cat /usr/local/etc/npmrc  # if it exists

Pay close attention to the path field in the error message — it tells you exactly which file or directory npm couldn't access. Once you identify the problematic path, apply the appropriate fix from the methods above.

Conclusion

The npm EACCES permission error is a signal that your Node.js environment has drifted into a state where system-level directories and user-level operations collide. While the quick fix of changing ownership with chown works, the recommended long-term solution is to adopt a Node version manager like nvm or fnm, which keeps everything neatly inside your home directory and eliminates the need for sudo entirely. By understanding the root cause — npm trying to write to root-owned directories — you can choose the fix that best fits your workflow, whether that's reconfiguring npm's prefix, resetting the cache, or migrating to a version manager. The key principle is simple: keep your development tooling within user space, and you'll never see an EACCES error again.

🚀 Need a reliable AI agent for your project?

Deploy Hermes Agent in 10 minutes. Managed hosting, zero DevOps.

Get Started — $23.99/mo
← Back to all articles