npm ERESOLVE Unable to Resolve Dependency Tree: How to Fix It

What does npm ERESOLVE unable to resolve dependency tree mean and what should you do first?
The npm ERESOLVE unable to resolve dependency tree error means npm could not find one set of package versions that satisfies every version range in your project. Usually a peer dependency clashes with an installed version. First read the error output, then move the conflicting package to a compatible version.
Do not reach for --force in a panic. That flag silences the warning, but it does not fix the conflict. The order below is the one that costs the least time and carries the least risk in our experience.
- Find the first conflict in the output: which package asks for which range.
- Run
npm explain package-nameto see why that package sits in the tree. - Upgrade or downgrade the conflicting package to a compatible version.
- If no compatible version exists, consider the
overridesfield inpackage.json. - As a last resort, use
--legacy-peer-depsand write down why. - Commit the lock file, so the error does not return on another machine or in CI.
What is the right order for fixing an ERESOLVE error?
The order runs from safest to riskiest. In practice, the first three steps repair the dependency tree for real. The last steps only let you ignore the conflict. In other words, find the cause first, then relax the rule only if you must.
We recommend this order for a simple reason. The conflict usually comes from one outdated package, so when you update it, several warnings disappear together. If you bypass the check with a flag instead, the problem can return in production as a very different bug.
This list is a diagnostic path, not a recipe. Retry the install after every step. If a step works, then stop there, because every extra change you make blurs what actually fixed the problem later.
How do you read the npm ERESOLVE output?
The output looks noisy, but it gives you three facts: what you tried to install, which version range that package wants, and which version already sits in the tree. So once you find those three, half the work is done.
You will usually see a Found line, a Could not resolve dependency line, and a tree fragment that points at the clash. However, the exact wording can differ between npm versions. So look for a similar message on your screen instead of expecting a word-for-word match.
- Found: the version that currently sits in the tree.
- Could not resolve: the range the package you are installing asks for.
- peer: the shared package that must stay compatible, such as a UI library.
- Fix the upstream dependency conflict: npm nudging you to fix the package itself.
For example, suppose the output says a plugin wants the previous major version of a library. Then the plugin is the problem. Also check whether the plugin has a newer release before you roll the library back.
Also save the terminal output to a text file. You can then search it, mark the conflicting package names, and send it to a teammate as is. A text paste helps others diagnose the issue faster than a screenshot.
What is a peer dependency and why is ERESOLVE more visible now?
A peer dependency is a package saying, "a compatible version of this other package must be installed next to me." A plugin does not bring its own copy of the main library. Instead it uses the one in your project, so the app runs a single copy.
Think of a spare part. It does not ship with its own engine, it fits the engine in your car. If the engine model is wrong, then the part does not fit. A peer dependency records that engine model.
Newer npm versions started installing peer dependencies automatically. Older versions only printed a warning and kept going. Now the install stops when ranges disagree, so the old clash becomes visible. So a project that installed fine for years can show an ERESOLVE error after you update npm. In most cases the conflict is not new, it just became visible.
Do not confuse this with a network failure. ERESOLVE is a tree resolution error, whereas connection problems arrive with different error codes. Also, the code sits in the heading. Read the code in the heading first, and you avoid searching in the wrong place for hours.
What causes npm ERESOLVE unable to resolve dependency tree most often?
We ordered the causes by likelihood. Check the first ones first, because in practice most cases end within the first two items.
- A plugin does not yet support the new major version of the main library.
- You updated the main library but not its plugins.
- Two different packages ask for incompatible ranges of a shared package.
- An old lock file pins versions that no longer fit.
- Your Node and npm versions differ from what the project expects.
- A private or mirrored registry returns incomplete metadata.
The table pairs the same causes with symptoms and fixes. Read it like the list above, but also look closely at the fix column.
| Cause | Symptom | Fix |
|---|---|---|
| Plugin stuck on an old range | Could not resolve, narrow peer range | Install a newer plugin release or roll the main library back |
| Half-finished upgrade | Only a few packages sit on the new version | Update the related packages together |
| Two packages want different ranges | Clash in two branches of the tree | Pin one version with overrides |
| Stale lock file | Error in a clean folder, none on the old machine | Refresh the lock file and node_modules |
| Wrong Node version | Same project behaves differently on two machines | Match the Node version to the project |
| Incomplete metadata | Package is found but its range cannot be read | Check the registry setting and the cache |
How do you fix npm ERESOLVE unable to resolve dependency tree by changing versions?
The most solid fix is choosing versions that support each other. First look at which ranges the package supports. The command npm view package-name peerDependencies shows that. Then install the matching version.
npm view plugin-name peerDependencies
npm install plugin-name@latest
npm install library-name@previous-majorThe decision is yours. If the plugin has a newer release, upgrading it is usually better, because you keep the security fixes of the main library. If the plugin is abandoned, rolling the library back is only a stopgap. Record it as a work item.
Read the changelog before you jump a major version. Breaking changes are usually listed there. Reading takes ten minutes, whereas while debugging a wrong version can take hours. Also move in small steps: upgrade one major version at a time.
Run the app after the upgrade, because a major bump can fix the install and still break behavior in your code. If you have a test suite, run it right after the install. Otherwise, at least open the main screens by hand.
How do npm explain and npm ls help you trace the conflict?
To see why a package sits in the tree, use npm explain package-name. The output shows which dependency pulled it in and which range that dependency asked for, as a chain. Then, once you find the chain, you have found the culprit.
npm explain library-name
npm ls library-nameThe command npm ls lists the installed tree. If you see two versions of the same package, there is one copy too many. However, a failed install can leave the tree incomplete. So start with npm explain, then confirm with npm ls after a successful install.
Also, npm outdated summarizes which packages fell behind. It catches the case where plugins lag behind the main library very quickly. That way you decide with data instead of guessing which package to touch.
What does --legacy-peer-deps do?
The --legacy-peer-deps flag tells npm not to install peer dependencies automatically and not to check their conflicts. In other words, npm goes back to the old behavior. Instead, you must install peer packages yourself, and a range mismatch no longer stops the install. The install succeeds, but the conflict stays.
npm install --legacy-peer-depsThe flag often "works" because it makes the error vanish. However, you should know why it works: npm skips the check. If the plugin is truly incompatible, the problem can appear at runtime. So when you use the flag, write the reason in the README or the pull request.
The flag also follows you, because you must type it on every new npm install, and someone who forgets sees the same error again. For that reason a shared team rule is cheaper than reminding people one by one.
For example, an old admin panel project uses a plugin that asks for the previous major version of a library. In practice the plugin may still work with the new version. In that case the flag is a reasonable temporary bridge, so use it. Still, do not forget to look for a current plugin release.
What does --force do and why is it riskier?
The --force flag tells npm to push the install through despite conflicts. The npm Docs also say it forces remote fetching and skips some safeguards. Check the current behavior in the official documentation.
The difference is this. --legacy-peer-deps only restores the old peer dependency logic. --force carries a broader "install no matter what" meaning. It accepts conflicting versions in the tree, and the result can be unpredictable.
- Two versions that break each other can end up side by side.
- The lock file can update to versions you did not expect.
- The problem shows up at runtime instead of at install time.
- A teammate hits the same error without knowing about your flag.
So do not make --force a routine fix. If you truly need it, then use it as a one-off experiment, test the result, and never turn it into a permanent setting. In short, a flag rescues you from the error but not from its cause.
What is the difference between --legacy-peer-deps and --force?
Both get the install through, but they ignore different things, so compare them. The table summarizes which risk each method carries. The general rule: version fix first, then overrides, then --legacy-peer-deps, and --force last.
| Method | What it does | Risk |
|---|---|---|
| Upgrade or downgrade a version | Makes the tree truly compatible | Low; test code behavior |
overrides | Pins one package version across the tree | Medium; the pinned version may not fit the package |
--legacy-peer-deps | Switches peer dependency checks to the old mode | Medium; mismatches can surface at runtime |
--force | Ignores conflicts and forces the install | High; unpredictable tree |
| Clean install | Resets the lock file and node_modules | Low; versions can drift unexpectedly |
How does the package.json overrides field fix an ERESOLVE error?
The overrides field lets you decide which version of a package npm installs anywhere in the tree. If a dependency of a dependency clashes, you add this field to package.json and pin the version. npm then applies that pin across the whole tree.
{
"overrides": {
"conflicting-package": "1.2.3"
}
}The version number above is made up. In your own project, read the npm explain output and pick the real range. The npm Docs describe the rule in the package.json overrides section. Also verify the exact syntax there.
This method beats flags because your decision stays visible in a file and travels with the team. However, if the pinned version falls outside the range the package asks for, the risk is yours. So leave a note next to the entry, and remove it once the package itself is updated.
Sometimes the root cause is that one package is installed in several versions at once. That is normal and mostly harmless. Still, for a peer dependency you need a single copy, and the clash appears exactly there.
When should you delete the lock file and node_modules?
A stale lock file can pin versions that no longer fit. The symptom is simple: you get the error in a clean folder, but the install passes on your old machine. In that case deleting the lock file and the node_modules folder and installing again makes sense.
rm -rf node_modules package-lock.json
npm installThis resolves every version again, so it produces a new tree. Therefore review the new lock file with a diff and test the app. Try it on a separate branch first. Then, if it goes wrong, going back is easy.
If the cache is corrupt, npm cache verify can help. However, do not make it your first step, because most ERESOLVE cases have nothing to do with the cache. Instead, the real cause is a range conflict.
How do you match the Node and npm version to the project?
The same package.json can produce different trees on different Node and npm versions. That is why "it works on my machine" is so common. First check your machine with node --version and npm --version, then check what the project expects.
- If the project has an
enginesfield, follow the range there. - If you use a version manager, keep a version file in the project.
- Also pin the same Node version in your CI environment.
- Confirm that everyone on the team uses the same major version.
A package can also ask for a newer Node range than you run. Then the install fails in a different way. To avoid mixing that up with ERESOLVE, read the title of the error message.
If you set up Node from scratch, our Node.js deployment guide covers the server side. For process management, see our PM2 article.
How do you keep the same error from returning in CI?
In CI, the goal is to install the same tree on every run. Commit the lock file, and use npm ci instead of npm install in CI. The npm ci command installs the exact versions from the lock file. It fails if the lock file and package.json disagree.
npm ciThat behavior works in your favor. So the mismatch shows up during development, not in a midnight production build. In other words, the error appears early. For details, read the npm ci page in the npm Docs.
If you must use a flag, write it out in the CI script. If you lean on a hidden local setting, your teammate and CI get different results. Then the "it passes for me" argument starts.
Is it a good idea to make --legacy-peer-deps permanent with .npmrc?
You can make it permanent, but be careful. Adding an .npmrc file to the project carries the setting to everyone on the team and to CI. That is good, because everyone gets the same result. The downside is that you switch off conflict checking completely.
legacy-peer-deps=trueThe exact name and behavior of the setting appear on the config page of the npm Docs. Check the current definition there. To see the current value, run npm config get legacy-peer-deps.
Our advice: add this setting only as a temporary bridge, and put the reason in a comment line in the file. Then remove it once you fix the conflict. A permanent flag turns into technical debt that nobody remembers years later.
A shared team rule helps too. For example, "every pull request that uses a flag states the reason in its description" costs little and adds a lot of transparency. Moreover, a new teammate learns why the setting exists without asking.
Does npm ERESOLVE unable to resolve dependency tree only appear on npm install?
No. The same conflict can appear on npm update, on npm install package-name, and in some CI steps. All of these commands recompute the dependency tree, and each time npm applies the same range rules.
So if you get the error while adding a new package, the new package is often not the culprit. Instead, it clashes with an older package in the tree. Find the other package named in the output first, then look at that package's peer range.
In a monorepo, several package.json files can share one root lock file. A range in one workspace then affects another. You can read which workspace the error comes from in the path of the npm explain output.
How do you structure a project to prevent dependency conflicts?
You cannot reduce conflicts to zero, but you can make them rarer. First, keep the dependency count low. Every extra package adds a new range rule to the tree. Remove unused packages at regular intervals.
Second, update in small, frequent steps. Waiting six months and then upgrading everything at once raises the odds of a clash. With small steps, then, finding the guilty package is easy.
- Look at the
npm outdatedoutput every month. - Upgrade the main library and its plugins in the same pull request.
- Watch abandoned plugins and plan an alternative.
- Always commit the lock file.
- Open a separate branch before upgrades.
Third, when you pick a new package, check its last update and the library versions it supports. Specifically, the peerDependencies field on the package page is an early sign of future conflicts. This check takes two minutes and saves hours of debugging.
Which questions should you ask before using a flag?
Using a flag is not forbidden. Instead, it should be a conscious decision. Answer the questions below in order. If three answers are "no", skip the flag.
- Does the conflicting package have a newer release, and did I try it?
- Does the plugin truly work with the new major version, and did I test it?
- Did I note the flag in the docs and tell the team?
- Did I set a date or condition to remove the flag?
- Does CI give the same result with the same flag?
These questions turn the flag from a shortcut into a planned workaround. As a result, your technical debt stays visible. A new developer also understands why the setting sits there.
What mistakes should you avoid with an ERESOLVE error?
These are the mistakes we see most often. Each looks small, but they get expensive as the project grows.
- Pasting the first command you find online without reading the error.
- Making
--forcethe default fix. - Leaving the lock file out of the repository.
- Deleting
node_moduleson every error and hoping for luck. - Rolling back a package with a security fix just to pass the install.
- Hiding from the team that you used a flag.
Also, do not delete a package just to make the install pass. The deleted package may be used elsewhere. Look at who depends on it with npm explain first.
Example scenario: why did an old admin panel project fail on a new machine?
This is an example scenario, not a real customer case. First, a team opens an admin panel project, set up two years ago, on a new computer. The project ran fine on the old machine, but the new one throws an ERESOLVE error.
Here is our diagnostic order. First we compare the Node and npm versions. The npm on the new machine is newer and installs peer dependencies automatically. Then we read the output: a chart plugin asks for the old major version of the UI library. With npm view we see that the plugin has a newer release.
To fix it, we upgrade the plugin, refresh the lock file, and test the screens by hand. No flag is needed. Therefore the lesson is clear: the problem was not new. The newer npm simply made an old conflict visible.
What is a practical checklist for an ERESOLVE error?
Use this short checklist for the next error and hand it to your team. Work through it in order, then note the result of each step.
- Write down the two conflicting packages and their ranges from the output.
- Confirm the chain with
npm explain. - Compare the Node and npm versions with the project.
- Move the conflicting package to a compatible version and test.
- If needed, pin one package with
overrides. - If you need a temporary bridge, use
--legacy-peer-depsand write down the reason. - Commit the lock file and run
npm ciin CI. - Track temporary settings with a work item.
For neighboring problems, see our existing articles. If you hit a memory error after installing, our JavaScript heap out of memory guide helps. For file clashes in version control, read how to resolve Git merge conflicts.
Is the problem in your code or in the dependencies?
Not every install failure is a dependency problem. For example, sometimes it is a build error, a TypeScript type mismatch, or a server environment difference. For a general approach, read our debugging techniques article.
If you wonder how type safety affects dependency management, see our TypeScript versus JavaScript comparison. If you plan to move the finished app to a server, our Next.js VPS deployment guide is a good companion.
Finally, record the fix somewhere. If you see the same error in another project six months from now, you will want to remember which step worked. A short note becomes the shared memory of the team and saves you from repeating research.
How can our team help with dependency and install problems?
At Talha Aslan and team, we work on dependency management, CI setup, and version policy in custom software projects. If your project has recurring install errors, we find the root cause together with you.
Install errors are often the first sign of a larger mess: outdated packages, undocumented settings, a build tied to one machine. Collecting these systematically reduces the outages you face later.
For this work you can request a quote through our custom software development service. We define the scope after reviewing your project. This article is not a technical guarantee; always verify command and setting behavior in the official npm documentation.



