npm audit fix is not working: why, and what to do instead
Updated 2026-11-03
npm audit fix applies remediations that fit the ranges already in your package.json. It does nothing useful when the patched release is a major bump, a transitive dependency your parent will not accept, or a release newer than your minimum age. Do not start with --force.
npm’s audit command sends a description of the dependencies in your project to the registry and prints known vulnerabilities. npm audit fix then tries to apply the remediations. npm’s own documentation says some vulnerabilities cannot be fixed automatically and need manual review, and that npm audit fix runs a full npm install underneath. A lockfile is required by default. Without package-lock.json or an npm shrinkwrap, the results can change between runs because npm rebuilds the tree.
The report line “fix available via npm audit fix” is not a promise that the next command will change your tree. The npm CLI had issue #9718 for that outcome, closed in July 2026 by a fix allowing safe downgrades. Check your npm version and release notes as well as dependency ranges. An unchanged tree alone does not identify the cause.
Read the audit before you run a fix
From the directory that contains package.json and the lockfile:
npm audit
npm audit --jsonFor each advisory, write down four facts. The package name. Whether you depend on it directly or it arrived through another package. The version you have, and the version the advisory says is patched. The severity. npm’s auditing guide is explicit that audit looks at dependencies, devDependencies, bundledDependencies, and optionalDependencies, and that it does not check peerDependencies. A clean report is not a promise about peers, and it is not a promise about code you wrote.
If the advisory says no patch is available, npm audit fix cannot invent one. npm’s guide then points you at mitigating factors, updating the parent if a fixed parent exists, patching it yourself, or opening an issue. An override to a version that does not exist will fail the install. Skip the rest of this page for that advisory and track the upstream release.
See what audit fix would change
npm audit fix --dry-run
npm audit fix --dry-run --jsonRead the JSON for the packages it would add or remove. If the dry run makes no changes and the advisory remains, inspect its warnings and the dependency chain; range constraints are one possible cause. npm documents the rule: when the chain of issues reaches your root project and the fix would change a dependency range, npm audit fix will not apply it unless you pass --force. When the fix fits inside the ranges you already declared, it updates the vulnerable packages without that flag.
Two other documented reasons the command looks broken:
| What you see | What npm is doing |
|---|---|
| Dry run changes nothing | Check the dependency chain, release-age settings, and npm version. A range constraint can block a fix, but an empty dry run does not prove one. |
You passed --only=prod | devDependencies are skipped. An advisory in a build tool stays until you drop the flag. |
| A warning that the fix was blocked | min-release-age or before refused a release that is too new. Exclude that package, or loosen the window. Do not turn the window off for the whole registry. |
Update one direct dependency on purpose
If the vulnerable package is in your dependencies or devDependencies, install the patched version yourself. Use the version the advisory names, not “latest”, when latest is a major you have not read.
npm install some-direct-package@1.4.2
npm auditReplace some-direct-package and 1.4.2 with the name and the patched version from the report. Commit both package.json and package-lock.json. Run the app’s test script and a production build. A direct bump of a framework such as Next.js is a migration, not an audit fix. Use the Next.js 15 to 16 checklist for that, and leave it out of a drive-by audit command.
Pin a transitive package with overrides
When the vulnerable package is not one you depend on directly, the parent’s range is what blocks the fix. npm’s package.json reference says an overrides entry in the root package.json replaces a package in the tree with another version. Overrides in installed dependencies are ignored. Only the root file counts.
{
"overrides": {
"some-transitive-package": "1.2.3"
}
}Again, those names are placeholders. Put the package the advisory names, and a version that contains the fix and still speaks the API the parent imports. Then:
npm install
npm ls some-transitive-package
npm auditnpm ls should show the overridden version. If the parent breaks with the patched version, narrowing the override will not make that pairing compatible. Upgrade or replace the parent, or choose another compatible fix. When a version is compatible with one parent but should not affect other consumers, scope it with npm’s nested form:
{
"overrides": {
"the-parent-package": {
"some-transitive-package": "1.2.3"
}
}
}You cannot override a package you depend on directly to a different spec than the dependency itself. npm raises EOVERRIDE. For a direct dependency, change the dependency range, or point the override at it with the $ form the same document describes. Do not keep a direct range and an override that disagree.
Current pnpm documents overrides at the root of pnpm-workspace.yaml in its dependency-resolution settings. Match the documentation to the pnpm version pinned by your project instead of copying an older pnpm.overrides example. Yarn’s field is resolutions, documented in Yarn’s manifest. Copying an npm overrides block into a pnpm or Yarn repo does nothing. Use pnpm audit, yarn audit on Yarn 1, or yarn npm audit --all --recursive on modern Yarn. Modern Yarn’s unqualified command checks only direct dependencies in the active workspace; the flags include all workspaces and transitive packages. A Lovable or Bolt project that committed pnpm-lock.yaml or yarn.lock is not an npm project for this purpose, even if the chat called it npm.
Re-run the audit and your tests
--force is the flag people reach for when the dry run was empty. npm’s config docs say it allows npm audit fix to install modules outside your stated ranges, including semver-major changes, and they say to leave it alone if you do not have a clear idea of what you want. A major bump of a top-level framework to clear a transitive advisory is how a generated app loses its build. If you do use it, run the dry run with --force first and read every top-level change.
npm audit fix --force --dry-run
npm test
npm run build
npm auditA remaining advisory after a successful override usually means a second copy of the package is nested where the override did not apply, or the patched version is still inside the vulnerable range. npm ls the-package shows the copies. Fix the one the advisory names.
Bots do not replace this. Dependabot and Renovate open pull requests. They do not decide that the override is safe. That comparison is in Renovate vs Dependabot.
An ERESOLVE failure is a different problem: the install could not build a tree. When --legacy-peer-deps is and is not a fix, see fixing npm ERESOLVE.
For weekly upkeep, you can manually create a recurring dependency-review task with Denly’s task schedules after connecting a project and runner. Configure its instructions and review gates before enabling it. The public report form below creates a report; it does not create a schedule or a pull request.
Commands and product behavior on this page were checked against the vendor documentation linked here on 3 November 2026. Those products change their screens. If a label has moved, follow the linked page rather than a memory of this one.
Read next
Renovate vs Dependabot, and when neither is enough · Upgrade Next.js 15 to 16: a practical checklist
Denly