npm audit fix fails with "npm ERR! code ERESOLVE" and leaves the tree half-resolved
Recovers from npm audit fix dying mid-run with ERESOLVE: restoring the lockfile from git, reinstalling clean, and applying the security fixes one package at a time instead of letting audit fix rewrite the tree blindly. Use when audit fix breaks the tree with peer-dependency conflicts. Not for ERESOLVE on plain npm install.
TL;DR
npm audit fix rewrites your dependency tree to apply security patches, and when it hits a peer-dependency conflict it dies halfway, leaving node_modules and the lockfile in a broken intermediate state. Restore both from git, reinstall clean, then apply the fixes selectively: bump the specific vulnerable packages yourself and resolve each ERESOLVE deliberately instead of letting audit fix guess.
The query
npm audit fix fails with "npm ERR! code ERESOLVE" and leaves the tree half-resolvedUse this when
- npm audit fix exits with ERESOLVE partway through
- node_modules or package-lock.json is left in a broken state after the run
- The audit report lists fixes you still need to apply
Not for
- ERESOLVE on a plain npm install (no audit fix involved)
- Audit fix completing but changing too much (review the diff, a different problem)
- Peer conflicts you introduced by hand-editing dependencies
Steps
1. Restore the tree to a known-good state
git checkout -- package-lock.json && rm -rf node_modules && npm ciExpected output: a clean install matching the committed lockfile. Never try to repair the half-written tree; replace it.
2. List what audit actually wants
npm auditExpected output: the vulnerability list with the recommended fix actions. You will apply these by hand, one at a time.
3. Fix the top vulnerabilities individually
For each fixable CVE, install the patched version of the specific package:
npm install [package]@[fixed-version]Expected output: npm either resolves it or reports an ERESOLVE naming the exact peer conflict. One conflict at a time is debuggable; twenty at once is not.
4. Resolve each ERESOLVE deliberately
Read the peer conflict: which package demands the old peer, and is that demand real or stale? Options in order of preference: upgrade the demanding package too, add an override for the peer, or accept the vulnerability as a tracked exception.
Expected output: each conflict ends with a conscious decision recorded somewhere (commit message, ticket).
5. Verify the final tree
npm ls [package] && npm auditExpected output: the tree is consistent (no ERESOLVE on install) and the audit count dropped by the fixes you applied. Commit the lockfile.
Variant phrasings
npm audit fix ERESOLVE half resolved tree
The short symptom search.
npm audit fix breaks node_modules peer dependency conflict
The cause-first search.
Compatibility: npm 7 and later, where peer dependencies are installed strictly and ERESOLVE is enforced.
Why it happens
npm audit fix is an automated tree rewriter: it computes a new tree with patched versions and applies it. Peer dependency constraints make some of those rewrites impossible, and npm aborts the operation after partially applying it. The half-resolved tree is not a corrupt state npm intended; it is the wreckage of an aborted rewrite.
Edge cases / pitfalls
- npm audit fix --force makes this worse, not better. It resolves conflicts by installing conflicting peer versions side by side, which usually breaks at runtime.
- Overrides (the overrides key) silence ERESOLVE but do not resolve the underlying incompatibility. Use them only when you have verified the combination works.
- If the vulnerable package is transitive, installing the fixed version directly adds it as a direct dependency. That is fine, but document why it is there.
- Some ERESOLVEs have no good answer: the fixed version genuinely conflicts with your stack. Then the fix is upgrading the stack or accepting the risk in writing, not fighting the resolver.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_TaHIHrZDGqhEl8Q4TOwXhw