How do I read npm "conflicting peer dependency" error messages? - npm

I'm in the process of trying to upgrade some npm dependencies of a project I own, and I'm getting a "conflicting peer dependency" error.
I see a lot of questions on this site asking for help fixing such errors. However, I've struggled to find information on what these errors actually mean. I feel like if I understood that, I'd have a chance of figuring out how to solve the problem on my own.
Here's the error message I'm trying to interpret:
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! Found: #angular-devkit/build-angular#0.1102.5
npm ERR! node_modules/#angular-devkit/build-angular
npm ERR! dev #angular-devkit/build-angular#"~0.1102.9" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! dev #angular-devkit/build-angular#"~0.1102.9" from the root project
npm ERR!
npm ERR! Conflicting peer dependency: #angular/localize#11.2.10
npm ERR! node_modules/#angular/localize
npm ERR! peerOptional #angular/localize#"^11.0.0 || ^11.2.0-next" from #angular-devkit/build-angular#0.1102.9
npm ERR! node_modules/#angular-devkit/build-angular
npm ERR! dev #angular-devkit/build-angular#"~0.1102.9" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
This can be reproduced by running npm install in the root of this Github branch (I'm using npm 7.10.0.)
My general understanding of a "conflicting peer dependency" error is that some package I depend upon is expressing a peer dependency on a package version spec which does not match the version of that package that I actually have installed.
For example, if my project has direct dependencies on packages A and B, and I have version 12.0.0 of A installed but my version of B has a peer dependency on ^11.0.0 of package A, then I will get a conflicting peer dependency error, because I'm using B with a version of A that it is potentially incompatible with.
Therefore, my best guess as to what this error message could mean is that some package I depend upon has a peer dependency on #angular/localize version spec ^11.0.0 || ^11.2.0-next, but this spec does not match the version of #angular/localize I have installed.
When I look at my package-lock.json, I do see that the node_modules/#angular-devkit/build-angular entry has an entry "#angular/localize": "^11.0.0 || ^11.2.0-next" in its peerDependencies.
However, this is the only mention of #angular/localize anywhere in this file -- or indeed in package.json. I haven't explicitly requested for it to be installed. Furthermore, it is marked as "optional": true in the peerDependenciesMeta of node_modules/#angular-devkit/build-angular. So it's surprising to see an error message related to it.
The error mentions that the specific conflicting peer dependency is #angular/localize#11.2.10. I don't see where that version number is coming from. But regardless, it actually seems to match the dependency specification underneath: if I go to semver.npmjs.com and type in #angular/localize as the package and ^11.0.0 || ^11.2.0-next as the version range, I see version 11.2.10 of the package highlighted in green, indicating that it matches the range.
So I'd really appreciate some help understanding in detail what this error message is telling me. I don't know why npm is trying to install 11.2.10 of #angular/localize, or why it thinks this conflicts with the peer dependency specification of #angular-devkit/build-angular. It feels like I might be misunderstanding this message completely.
I'm guessing this boils down to some kind of incompatibility between the latest published versions of some of the Angular packages. If anyone has any pointers on how this particular error should be fixed, that would be great -- but I'm much more interested in simply understanding what the error message is telling me, so I can work it out for myself.

Recommendation:
Check out Yarn.
I was able to circumvent the issue in NPM by using Yarn instead of NPM. Yarn is basically a wrapper utility around NPM that adds extra features, which are super useful. It's especially helpful for managing NPM dependencies better.
For instance, it can check if a package is already installed on your machine for another project, directly or as a sub dependency, and can reuse that installed version rather than re-installing a copy of the same package; saves space and makes for faster installations, especially with some of the most common dependencies.
So, due to the optimized way Yarn handles dependencies, I think it helps avoid this issue faced by the OP.
Resolution:
First, delete the node_modules folder in your project.
Yarn will complain about any package-lock.json files, so delete that too (or back it up, then delete it). Do not delete package.json, yarn will need that.
Simply install yarn: npm i yarn (you could do this globally, too).
Then run yarn install in your project directory.

Reading through this GitHub issue, it appears my interpretation of the error message was correct, and that this is in fact a bug in npm.
This appears to have been reported as npm/cli/issues/3083; a fix has been merged, so I guess we just have to wait until it gets included in some upcoming npm release.

Related

NPM equivalent of maven's install:install-file goal

I've come across an issue where one of my transitive dependencies went missing from the NPM registry, either due to a user error, or some other action. Being used to converting plain java projects to maven, I would depend on install plugin and install-file(1) goal to create a pom.xml file for that jar (a package.json equivalent), and it would be put into local repository under .m2 folder. Afterwards other projects could refer to it as if the package was available remotely.
In NPM I'm seeing that an equivalent to "referring to local package" works via link sub command, but what it really does is writes absolute path on local system to the needed package. That is great in scenario when you control a dependent package, but not so much when you don't.
I've also attempted to do the naive way of "installing a package globally" (such as using github tarball), because on github the release, and source code are still present. But since the tool that's also fetched from the NPM registry specifies that it must pull dependencies from the registry ignores the globally installed version of that library and fails. The command line of this would be as follows:
npm install -g https://github.com/{user}/{repo}/tarballs/{tag}
added 915 packages from 60 contributors
npm install -g "foo-cli#{tag}"
npm ERR! code ETARGET
npm ERR! notarget No matching version found for {repo}#^{tag}.
npm ERR! notarget In most cases you or one of your dependencies are requesting
npm ERR! notarget a package version that doesn't exist.
npm ERR! notarget
npm ERR! notarget It was specified as a dependency of 'foo-cli'
npm ERR! notarget
This does raise several questions:
Does local registry exist?
How do I tell NPM to first check "locally installed" versions for tools I do not control?
Am I stuck forking the tool to "link" it against my locally installed version of missing library?

Modifying an npm package locally to manually fix dependency tree issues?

In the process of learning nest.js, I've run into an npm dependency tree issue.
I'm attempting to do something like npm install --save-dev #types/bcrypt #types/passport #types/passport-jwt. This (and similar npm commands) will throw this error:
npm ERR! code ERESOLVE
npm ERR! ERESOLVE could not resolve
npm ERR!
npm ERR! While resolving: #nestjs/passport#8.2.1
npm ERR! Found: passport#0.6.0
npm ERR! node_modules/passport
npm ERR! passport#"^0.6.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer passport#"^0.4.0 || ^0.5.0" from #nestjs/passport#8.2.1
npm ERR! node_modules/#nestjs/passport
npm ERR! #nestjs/passport#"^8.2.1" from the root project
npm ERR!
npm ERR! Conflicting peer dependency: passport#0.5.3
npm ERR! node_modules/passport
npm ERR! peer passport#"^0.4.0 || ^0.5.0" from #nestjs/passport#8.2.1
npm ERR! node_modules/#nestjs/passport
npm ERR! #nestjs/passport#"^8.2.1" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
I've traced the problem to the following:
I currently have version 8.2.1 of #nestjs/passport installed - this was released on Feb 16
I can see in my local folder of node_modules/#nestjs/passport/package.json that it has the dependency "passport": "^0.4.0 || ^0.5.0 , as the terminal error implies
In the current Github version of #nestjs/passport, however, I see that they've updated that line to include || ^0.6.0 in late May link
#nestjs/passport hasn't created a new release with this (and other) updates yet though.
Two things I'm wondering:
How can I resolve this dependency issue now, before the maintainers of #nestjs/passport publish their next release?
Why doesn't it work for me to go into my local node_modules/#nestjs/passport/package.json file and manually change it to include ^0.6.0? (After doing that, saving the file, and trying the npm commands again, I still get the same dependency errors)
NPM has already answered the question for you, there are two solution you can try, either run :
npm install --legacy-peer-deps
This section from the npm blog explains what that command does:
We have identified automatic peerDependencies installation as a potentially disruptive change for many users (albeit one that we are confident is the correct behavior for a package manager), we have some tools to minimize this disruption, based on the feedback we get.
We are confident that resolving package trees such that peerDependencies are properly accounted for is the right thing to do. After all, an error here can result in a production issue that’s very difficult to debug later, especially if it occurs deep in a node_modules tree. However, years of not resolving peerDependencies has allowed many projects to fail to notice these problems.
In order to get unblocked and install your project in spite of peerDependencies conflicts, you can use the --legacy-peer-deps flag at install time. It may be that the disruption is too great to take all at once, and we have to have this flag enabled by default for a while as projects gradually update their conflicting dependencies. Our intent is to let the beta give us some more data points to help make that decision carefully.
Or force passport into installing (I'm not sure that is recommended)
npm install [package] --force
This will force npm to fetch remote resources even if a local copy exists on disk.
Good Luck.

NPM 8 workspaces - Install one package as the dependency for another package in monorepo

Say I have the following structure
packages
- #my-scope/packageA
- #my-scope/packageB
- #my-scope/packageC
Let's say I want to install packageA as a dependency of packageB. With NPM 8 workspaces I would think this ought to do it:
npm install #my-scope/packageA --workspace=#my-scope/packageB
Instead I get this:
npm ERR! 404 Not Found - GET https://registry.npmjs.org/#my-scope%2fpackageA - Not found
npm ERR! 404
npm ERR! 404 '#my-scope/packageA#*' is not in this registry.
npm ERR! 404 You should bug the author to publish it (or use the name yourself!)
npm ERR! 404
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.
Clearly it is trying to get it from the registry (and no, I haven't published yet, not ready) but I want it to recognize that this dependency is in my project as a workspace. Anyone know why this might be happening? I haven't found many good resources explaining how to install dependencies from inside your monorepo (I don't even know what those are called...).
The problem you are facing has been reported as a bug: https://github.com/npm/cli/issues/3637
It has been marked as fixed.
Please try to install the latest version of npm (8.8.0 as of this writing) and see if your problem has been resolved.

How to fix "npm ERR! Errors were found in your package-lock.json"

I am getting the follow error in npm. what does this mean please and how may I fix this error?
npm ERR! code ELOCKVERIFY
npm ERR! Errors were found in your package-lock.json, run npm install to fix them.
npm ERR! Invalid: lock file's #angular/animations#12.1.3 does not satisfy #angular/animations#~12.1.0-
npm ERR! Invalid: lock file's #angular/common#12.1.3 does not satisfy #angular/common#~12.1.0-
npm ERR! Invalid: lock file's #angular/compiler#12.1.3 does not satisfy #angular/compiler#~12.1.0-
npm ERR! Invalid: lock file's #angular/core#12.1.3 does not satisfy #angular/core#~12.1.0-
npm ERR! Invalid: lock file's #angular/forms#12.1.3 does not satisfy #angular/forms#~12.1.0-
npm ERR! Invalid: lock file's #angular/platform-browser#12.1.3 does not satisfy #angular/platform-browser#~12.1.0-
npm ERR! Invalid: lock file's #angular/platform-browser-dynamic#12.1.3 does not satisfy #angular/platform-browser-dynamic#~12.1.0-
npm ERR! Invalid: lock file's #angular/router#12.1.3 does not satisfy #angular/router#~12.1.0-
npm ERR! Invalid: lock file's #angular/compiler-cli#12.1.3 does not satisfy #angular/compiler-cli#~12.1.0-
I know that sometimes the previous solutions don't always work, which does seem to be the case with the latest release of Angular's CLI.
Here are the steps I used to fix my issue:
Remove package-lock.json rm package-lock.json
Under the dependencies & devDependencies sections in your package.json update any version number that looks like ~12.1.0-
Then run npm install
Hope this helps you solve the issue you are having.
Have a good one :)
Matthew
Unfortunately deleting package-lock.json and running npm install won't work in this instance. I had the exact same error after running ng new. After reviewing npm versioning and scratching my head for bit, I did the following (which fixed it):
Deleted package-lock.json
Deleted node_modules
Ran npm cache clean --force
Edited package.json for each of the referenced libraries and changed the "0-" to "3" (e.g. "#angular/animations": "~12.1.3" instead of "#angular/animations": "~12.1.0-")
I don't know if all of the steps were completely necessary, but whenever I start running into any npm weirdness that doesn't have an obvious fix, I always do steps 1 thru 3.
As for the meaning of the error message, each line is indicating that the version of the library which has been installed fails to fall within the range of versions you have indicated (within your package.json) you will accept.
The mystery to me is how/why version 12.1.3 of anything would be installed if my package.json indicated 12.1.0. The trailing "-" clearly has something to do with it, but I didn't see anything about it being part of the npm versioning syntax (linked above). And while the Semantic Versioning Spec does indeed allow for hyphens for indicating a pre-release version, it MUST be trailed by something.
rm package-lock.json
npm install
Remove the trailing - from package.json for all the packages mentioned in the error message.

resolving npm shrinkwrap peer invalid dependencies

I've inherited a react/node/prismic application that uses shrinkwrap, and we need to update the prismic-reactjs package. That package requires higher versions of react and webpack, so I updated those in package.json too, and based on some npm dependency reading I've been roughly following these steps:
rm -fr node_modules
npm uninstall [package_name]
npm prune
npm cache clean
npm install [package_name]
npm shrinkwrap (to check missing dependencies)
npm install
npm shrinkwrap
That last shrinkwrap step shows the remaining "npm ERR! peer invalid:" statements, so I've been working my way top to the bottom of the list, and I'm now down to only three of them:
npm ERR! peer invalid: webpack#^3.1.0, required by extract-text-webpack-plugin#3.0.2
npm ERR! peer invalid: react#^15.6.1, required by react-dom#15.6.1
npm ERR! peer invalid: react#^15, required by react-router-dom#4.1.2
Uh oh- it looks like those peer dependencies need the older versions I'd had for webpack (I updated 3.12.0 -> 4.0.0) and react (I updated 15.6.1 -> 16.0.0).
Of those 3 other packages, one is deprecated so I can't upgrade it if I tried. I could try updating the other 2, but I'm not sure if this is yak shaving- is there a better way forward? Is it possible to have both/conflicting packages in use?