Why or when does npm sometimes allows conflicts with a warn (`overriding peer dependency`) instead of an error (`could not resolve`)?

134 views Asked by At

Tl;dr: overriding peer dependency vs could not resolve in npm.


Since npm 7, npm no longer allows installing with peer dependencies conflicts,
so errors like this are expected:

npm ERR! code ERESOLVE
npm ERR! ERESOLVE could not resolve
npm ERR! 
npm ERR! While resolving: [email protected]

But I've also seen non blocking peer dependencies resolution conflicts,
that result in a simple WARN instead of ERR!,
and npm is happy to override the conflicting requirement:

npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: [email protected]
npm WARN Found: [email protected]
npm WARN node_modules/react
npm WARN   peer react@">=16" from [email protected]
npm WARN   node_modules/___
npm WARN     ___@"^x.x.x" from the root project
npm WARN   42 more (___, ___, ___, ...)
npm WARN 
npm WARN Could not resolve dependency:
npm WARN peer react@"^0.14 || ^15.0.0 || ^16.0.0-alpha" from [email protected]
npm WARN node_modules/airbnb-prop-types
npm WARN   airbnb-prop-types@"^2.8.1" from [email protected]
npm WARN   node_modules/react-dates
npm WARN 
npm WARN Conflicting peer dependency: [email protected]
npm WARN node_modules/react
npm WARN   peer react@"^0.14 || ^15.0.0 || ^16.0.0-alpha" from [email protected]
npm WARN   node_modules/airbnb-prop-types
npm WARN     airbnb-prop-types@"^2.8.1" from [email protected]
npm WARN     node_modules/react-dates

Do you know in which case npm overrides instead of failing?
Is there documentation on the subject?

(And is there a way, as a library author to relax a peer dependency so that it can be overridden?)

1

There are 1 answers

0
Yann Dìnendal On

The project installing a dep with conflicting peerDeps can force installation of the specific conflicting dependency with the overrides section of the package.json: https://docs.npmjs.com/cli/v10/configuring-npm/package-json#overrides

This is better than legacy-peer-deps, as it's fine-grained and explicitly lists which peerDep constraints are overridden instead of being an open bar of conflicts.

Example:

   "overrides": {
    "react": "^17.0.2"
   }

or better:

   "overrides": {
    "react": "$react"
   }

so the override is kept in sync with the local dependency.