npm ERESOLVE unable to resolve dependency tree
Why npm 7+ refuses to install over a peer-dependency conflict, how to read the ERESOLVE report, and when --legacy-peer-deps is the safe way through.
Last updated
npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree npm ERR! npm ERR! While resolving: my-app@1.0.0 npm ERR! Found: react@17.0.2 npm ERR! node_modules/react npm ERR! react@"^17.0.2" from the root project npm ERR! npm ERR! Could not resolve dependency: npm ERR! peer react@"^18.0.0" from some-package@2.0.0
What it means: npm (v7 and later) enforces peer-dependency ranges strictly, and it found two packages requiring incompatible versions of the same dependency — it's refusing to guess which one should win.
Likely causes
Most probable first — with how to confirm.
- 1.A package you're adding declares a peerDependency range that conflicts with a version already pinned elsewhere in your tree — read the 'Found' vs. 'Could not resolve' lines in the error to see exactly which two versions clash.
- 2.One of your dependencies hasn't published a version with updated peer ranges yet, even though it may work fine in practice with the newer major version — check that package's changelog or open issues for known peer-range lag.
- 3.You upgraded one package in a related family (e.g. one plugin in a Babel or ESLint set) without upgrading the others, so their peer ranges no longer agree with each other.
Fixes
Safest first; destructive ones are called out.
- →Update the conflicting packages to versions whose peer ranges actually agree, if a compatible combination exists — check each package's published peerDependencies first.
- →Use `npm install --legacy-peer-deps` to fall back to npm 6's looser peer resolution — reasonable once you've manually confirmed the versions genuinely work together.
- →Treat `npm install --force` as a last resort: it can install a tree that doesn't actually satisfy peer requirements and cause runtime bugs rather than install-time ones.
- →If only one package is causing the clash, narrow its peer requirement with npm's `overrides` field in package.json instead of forcing the whole install.
Part by part
- ERESOLVE
- npm could not find a set of versions satisfying every declared dependency at once. This is a resolution failure, not a network or permissions one.
- npm ERR!
- The standard prefix. The lines that follow name the conflicting packages and which one demanded what.
Common mistakes
npm install --forceInstalls a tree npm has just told you is inconsistent. It usually appears to work and fails later at runtime, in a place with no obvious connection to the dependency that was forced.
npm install --legacy-peer-depsRestores npm 6 behaviour of ignoring peer dependencies entirely. It is a legitimate escape hatch for an unmaintained package, and a bad default — it silences the whole class of warning rather than the one conflict.
Deleting package-lock.jsonResolution is computed from package.json, so removing the lockfile does not change the conflict. It does discard the working version set you had, which makes it strictly worse than doing nothing.
Questions
How do I read the conflict?
npm prints which package requires which version of what. Find the package with the narrowest requirement — that is the one blocking the upgrade, and updating or replacing it is usually the real fix.
What is a peer dependency anyway?
A declaration that a package expects its host to provide something rather than bundling it — a plugin needing a specific framework version, typically. npm 7 began enforcing them, which is why this error appeared in projects that had been quiet for years.
When is --legacy-peer-deps acceptable?
When a dependency declares a peer range that is genuinely too narrow and is not maintained. Record why in a comment, because the flag hides every future conflict too, including ones that matter.
Is there a way to override just one dependency?
Yes — the overrides field in package.json pins a specific transitive version without disabling peer checking everywhere. It is targeted, visible in review, and far preferable to a blanket flag.