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.
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 -60Interpretation
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> --allInterpretation
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
- Upgrade the package that declares the older peer range.
- Align duplicated shared dependencies on one compatible major.
- Recreate the lockfile with a clean install.
- Add an
overridesentry 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 cisucceeds from a clean checkout.npm lsreports no invalid peer dependencies.- The application builds and the tests pass.
- The lockfile is committed.
- No
--legacy-peer-depsor--forceflag 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.