← Debugging Guides

阅读中文版本

npm ERESOLVE — Peer Dependency Conflict

Resolve npm ERESOLVE errors by reading the dependency tree, aligning peer ranges, deduplicating versions, and using overrides only with a documented reason.

intermediatedebuggingnpmdependenciesnodejs

Symptoms

  • npm ERR! code ERESOLVE and npm ERR! Could not resolve dependency
  • Installation fails after adding or upgrading a package, while the previous lockfile installed fine
  • The error mentions a peer dependency range that conflicts with a version already in the tree

Possible causes

  • Two packages require incompatible versions of the same peer dependency
  • A stale lockfile or duplicated package versions keep an old peer range alive
  • The package requires a newer Node.js or npm version than the current environment
  • A manual version override conflicts with a package's declared peer range

Diagnosis steps

Read the full conflict, including the two required ranges

npm install 2>&1 | head -60

Interpretation

The error names the package being installed, the conflicting peer, and the ranges. Compare semantic versions rather than package names alone.

Inspect the installed tree for duplicates

npm ls <peer-package> --all

Interpretation

Multiple versions of React or a shared library often explain why peer ranges cannot be satisfied.

Check what requires the conflicting version

npm explain <package-name>

Interpretation

The explanation shows the dependency path. Upgrade or replace the package that pins the old range.

Root cause

npm builds a single dependency tree that must satisfy every declared peer range. When two packages require incompatible ranges for the same peer, or the lockfile contains a version outside the required range, npm refuses to produce a tree and exits with ERESOLVE.

Fix

Upgrade the packages that declare old peer ranges, align shared dependencies on one compatible major version, remove stale lockfile entries with a clean install, and use overrides only when the incompatibility is understood and tested. As a temporary, documented last resort, install with legacy peer semantics.

Risk note

Using --legacy-peer-deps or --force bypasses the check and can produce a runtime failure that the peer range was warning about. Never add it to CI silently.

Verify the fix

Run npm ci in a clean checkout, then npm ls to confirm no invalid peer warnings, and run the test suite and a production build. Commit the regenerated lockfile and record why any override exists.

The tree must satisfy every range

npm 7+ treats peer dependencies as constraints during install. If package A needs React 18 and package B declares React 17 as a peer, no single tree can satisfy both unless an upgrade or override resolves the range.

npm install 2>&1 | head -60
npm ls react --all
npm explain react

Fix strategy

  1. Upgrade the package that declares the older peer range.
  2. Align duplicated shared dependencies on one compatible major.
  3. Recreate the lockfile with a clean install.
  4. Add an overrides entry only if you can test the combination:
{
  "overrides": {
    "some-package": {
      "react": "$react"
    }
  }
}

$react refers to the version resolved by the root project, which keeps the override aligned. Document why the override exists and remove it when upstream catches up.

Verify

  • npm ci succeeds from a clean checkout.
  • npm ls reports no invalid peer dependencies.
  • The application builds and the tests pass.
  • The lockfile is committed.
  • No --legacy-peer-deps or --force flag is required in CI.

When a workaround is acceptable

A short-lived --legacy-peer-deps may unblock a local experiment, but it changes resolution semantics and can hide real incompatibilities. Record the reason, the affected package, and a removal date. Do not make it the default for the repository.