Deploy Error Decoder

'npm ERESOLVE' — resolve the peer dependency conflict

Quick answer: npm 7+ refused to install because a package's peerDependency conflicts with what you have - for example a plugin wants react@17 but you installed react@18. The right fix is to upgrade the conflicting package to a version that supports your peer, or align versions. As a documented stopgap, --legacy-peer-deps restores the old behavior and unblocks the install.

Not your exact error? Paste it into the Deploy Error Decoder →

What the error looks like

npm spells out the conflict - read the peer lines carefully:

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR! Found: [email protected]
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^17.0.0" from [email protected]

It found react@18 but some-plugin declares a peer of react@^17. The two cannot coexist by the rules the package authors declared, so npm stops.

Why it happens

Peer range excludes your version

A package wants react@^17 but you installed react@18.

Two packages want different peers

Two dependencies require conflicting versions of a shared peer.

Package not updated for the new major

The library has not published support for React 18 (etc.) yet.

Stale or impossible lock file

An old lock file encodes a tree that no longer resolves cleanly.

Diagnose it in three steps

1

Read which package wants which peer

# the "peer X from PKG" line names the culprit and the version it requires.
2

Does a newer version support your peer?

npm view some-plugin peerDependencies
npm view some-plugin versions --json | tail
# is there a release that lists react@^18?
3

Choose: upgrade, override, or stopgap

# prefer upgrading the package that lags behind your peer.
The real fix

Upgrade the lagging package, or override deliberately

The clean fix is to upgrade the conflicting package to a version that supports your peer. If none exists yet, pin a verified-compatible version with overrides, or use the documented stopgap and test thoroughly.

# best: upgrade the package that lags behind your peer
npm install some-plugin@latest

# surgical: override a transitive version you have verified is compatible
// package.json
"overrides": { "some-plugin": { "react": "$react" } }

# stopgap - restores npm 6 behavior, accept and document the risk:
npm install --legacy-peer-deps

Whichever you choose, commit the resulting package-lock.json and use the same npm version in CI, so the install resolves the same way everywhere instead of failing only in the pipeline.

How Infraveil handles this

Reproducible installs, the same everywhere

An ERESOLVE that only fails in CI is a reproducibility gap - a different npm version or an unpinned tree. On your own servers, Infraveil runs deploys from a pinned, reproducible install and catches a failed install before it ships, so the resolution you tested is the one that runs - with the choice (upgrade or override) recorded, not a silent --force in CI.

One pinned npm/Node and lock file across every install, on infra you control
Failed installs caught and surfaced before production
Dependency decisions recorded, not buried in a CI flag

Frequently asked questions

What does ERESOLVE mean?

From npm 7, peer dependencies are enforced. ERESOLVE means npm could not build a tree because a package requires a peer version that conflicts with one already present. The error names the package, the version it wants, and the version found.

Is --legacy-peer-deps safe?

It restores npm 6's behavior of ignoring peer conflicts. It often works, but you are installing a combination the package did not declare support for - verify the app runs and test it, and treat it as a deliberate, documented choice.

What is the difference between --legacy-peer-deps and --force?

--legacy-peer-deps only ignores peer dependencies. --force also overwrites and bypasses other conflicts, which can produce a broken tree. Prefer --legacy-peer-deps; use --force only as a last resort and verify the result.

How do npm overrides work?

The overrides field in package.json forces a specific version for a dependency anywhere in the tree, including transitive ones. Use it to pin a peer to a version you have verified is compatible - more surgical and recorded than a blanket --legacy-peer-deps.