Devpuff
Pricing
Log InStart Free
  1. Home
  2. Blog
  3. npm install errors: read the code, not the stack
Tools

npm install errors: read the code, not the stack

Every npm ERR code names one cause. ERESOLVE, E404, EJSONPARSE and the rest, with what each one means, measured against real installs.

By Max Arthur
Co-Founder & Content Marketer·October 6, 2026·8 Min read
White text reading 'How to fix npm install errors' on a dark purple dotted background

Every npm failure starts with a line that names the cause:

npm error code ERESOLVE

That code is the diagnosis. The forty lines underneath it are supporting detail, and reading them before the code is why npm errors feel impenetrable. Six codes account for almost everything you will hit.

Code What it means
ERESOLVE Two packages want different versions of the same dependency
E404 The package name does not exist in the registry
EJSONPARSE Your package.json is not valid JSON
EUSAGE The command was used wrong, commonly npm ci with no lockfile
EACCES Permission denied, usually from a global install
ENOENT A file or directory npm expected is not there

Every output below came from real installs on npm 11.

ERESOLVE: a peer dependency conflict

The most common and the most misread. Here is a genuine one, produced by asking for React 17 alongside a library that requires 18 or 19:

npm error code ERESOLVE
npm error ERESOLVE unable to resolve dependency tree
npm error
npm error While resolving: conflict-demo@1.0.0
npm error Found: react@17.0.2
npm error node_modules/react
npm error   react@"17.0.2" from the root project
npm error
npm error Could not resolve dependency:
npm error peer react@"^18.0.0 || ^19.0.0" from @testing-library/react@16.1.0

Two lines matter. Found: is what your project asks for. Could not resolve dependency: peer is what something else demands. You asked for React 17, and @testing-library/react requires 18 or 19. Those cannot both be true.

A peer dependency is a package saying "I work alongside this, but you install it, and it has to be a version I support". npm 7 and later enforce that. npm 6 did not, which is why old advice and old projects behave so differently.

The honest fix is to make the versions agree: upgrade React, or install a version of the library that supports React 17. npm info @testing-library/react peerDependencies tells you what a version wants before you commit to it.

What --force and --legacy-peer-deps actually do

npm suggests both flags in the error text and explains neither. Installing the same broken project with each produced measurably different trees:

Flag Packages installed React version
--legacy-peer-deps 6 17.0.2
--force 18 17.0.2

--legacy-peer-deps ignores peer dependencies entirely, behaving like npm 6. It installed six packages and never tried to satisfy the peer requirement at all.

--force installs anyway, pulling in the peer packages and warning about each one. It installed eighteen packages, including the React DOM that @testing-library/react asked for, while leaving React itself at the version the library rejects.

Both leave the same underlying mismatch: React 17 alongside a library that does not support it. Neither is a fix. --legacy-peer-deps is the safer of the two because it changes less, and it is a reasonable holding measure while you sort out the real version problem. Treat either flag as a note to come back, not as a resolution.

E404: the package does not exist

npm error code E404
npm error 404 Not Found - GET https://registry.npmjs.org/this-package-truly-does-not-exist-9f3a2b

Usually a typo. Occasionally a private package you are not authenticated for, or a scoped name missing its scope (@org/thing, not thing).

It is also what you get from a package name an AI assistant invented. That deserves more than a quick correction, because the name being unregistered is the good outcome. AI hallucinations in code covers what happens when somebody has already registered it.

EJSONPARSE: your package.json is malformed

npm error code EJSONPARSE
npm error JSON.parse Invalid package.json: Expected double-quoted property name in JSON at position 12
npm error JSON.parse Note: package.json must be actual JSON, not just JavaScript.

That last line is npm anticipating the mistake. package.json is JSON, not JavaScript, so trailing commas are illegal, comments are illegal, and every key needs double quotes. The position number counts characters into the file.

EUSAGE: npm ci without a lockfile

npm error code EUSAGE
npm error The `npm ci` command can only install with an existing package-lock.json

npm ci and npm install are different commands, and the difference matters more than the names suggest:

  • npm install reads package.json, resolves versions, installs, and writes package-lock.json. It can change your lockfile.
  • npm ci reads package-lock.json, deletes node_modules, and installs exactly what the lockfile says. It never changes the lockfile, and it fails if the lockfile and package.json disagree.

That is why npm ci belongs in CI and npm install belongs on your machine. A build running npm install can quietly get different versions than you tested with. A build running npm ci cannot.

EACCES: permission denied

Almost always a global install on macOS or Linux:

npm install -g some-tool
# npm error code EACCES

The advice you will find most often is to prefix it with sudo, and it is the wrong answer. Running an installer as root lets any package's install script run as root on your machine, and it leaves root-owned files in your npm cache that cause fresh permission errors later.

The right fix is to stop needing root at all. A version manager such as nvm or fnm puts Node and its global packages inside your home directory, where you already have permission. For a tool you need once, npx some-tool runs it without installing globally.

ENOENT: npm is looking at the wrong folder

npm error code ENOENT
npm error syscall open
npm error path /your/current/folder/package.json
npm error enoent Could not read package.json

ENOENT is "error, no entry", and the path line names exactly what npm could not find. When that path ends in package.json, you are running npm somewhere that is not a Node project.

Nearly always this is the same mistake as running git outside a repository: the terminal opened somewhere else, or you are one directory above the project. ls and cd fix it. It is worth checking the path line before anything else, because it tells you which folder npm thinks it is in, and that is usually the entire bug.

A different ENOENT comes from a script pointing at a file that does not exist:

Error: Cannot find module '/your/project/missing.js'

Here npm ran your script correctly and Node could not find the file. Check the path in scripts, and check the file was actually committed rather than sitting untracked on the machine where it works.

Before you delete node_modules

Deleting node_modules and the lockfile is the folk remedy for everything, and it does fix a genuinely corrupted tree. It also throws away the record of which versions worked, which is the thing you most want when something is broken. Try the cheaper steps first:

  1. Read the code. Half of these need no reinstall at all. EJSONPARSE is a text edit.
  2. npm ci. Rebuilds node_modules from the lockfile exactly, without touching the lockfile.
  3. npm cache clean --force, if you suspect a corrupted download.
  4. Then delete node_modules, keep package-lock.json, and run npm ci.

Deleting the lockfile is the last resort rather than the first, because it re-resolves every version and can hand you a different tree than the one that used to work.

Reading the dependency path

The block of lines under an ERESOLVE is a path, and once you know the shape it is quick to read:

npm error Found: react@17.0.2
npm error node_modules/react
npm error   react@"17.0.2" from the root project

Each entry is three lines: the resolved version, where it sits in node_modules, and who asked for it. from the root project means your own package.json. Anything else names the package that wants it.

That last line is what tells you whether the conflict is yours to fix. A demand coming from the root project is a version you chose and can change. A demand coming from a dependency of a dependency means you are choosing between upgrading the package in the middle, waiting for its maintainer, or overriding the resolution yourself with an overrides block in package.json.

npm ls <package> prints the same relationship for an installed tree and is usually easier to read than the error.

Making these readable

Two habits help more than any flag.

Read the first five lines, then stop. The code and the two or three lines under it contain the diagnosis. The rest is the dependency path, which is useful only once you know what you are looking for.

Keep Node and npm versions consistent across a team. A large share of "works on my machine" installs comes from one person on npm 6, where peer conflicts were silently ignored, and another on npm 11, where they are hard errors. An engines field in package.json and a .nvmrc file make that mismatch visible instead of mysterious.

Want to work through installs and dependency trees somewhere they cannot break your machine? Start with the JavaScript track.

Keep reading

More from the blog

White text reading 'How to resolve merge conflicts in Git' on a dark purple dotted background
October 29, 2026·8 min readTools

How to resolve merge conflicts in Git

A Git merge conflict happens when two branches change the same lines. How to read the markers, resolve each file, and the check that stops a bad commit.

Read more
White text reading 'Git vs GitHub' on a dark purple dotted background
October 28, 2026·7 min readTools

Git vs GitHub: they are not the same thing

Git vs GitHub: Git is the version control tool on your computer, GitHub is a website that hosts Git repositories. What each one does and how they fit.

Read more
{ }
✦

Ready to write some code?

Put this into practice - start your first free lesson. No setup, no credit card.

Start learning free
Devpuff

Learn to code by doing. One tiny, playful lesson at a time.

Learn
ProgramsCoursesPricing
Company
AboutBlogResourcesAffiliates
Support
Help CenterContactStatus
Programs
Frontend DevelopmentFull-Stack DevelopmentReact DeveloperPython Developer
Courses
Advanced ReactAsync JavaScriptAsync PythonCSS BasicsCSS LayoutDSA Basics
Learn to Code
Learn JavaScriptLearn PythonLearn SQLLearn HTMLLearn CSSLearn ReactBrowse All Topics
Platform Comparisons
Devpuff vs CodecademyDevpuff vs Mimo
© 2026 Devpuff. All rights reserved.Privacy PolicyTerms and ConditionsCookies PolicyRefund Policy
Devpuff vs Sololearn
Devpuff vs freeCodeCamp
Read All Comparisons