When resolving a peer dependency that has a ">=" in it's version, npm uses the latest version of that package to compare with the current dependency version in the package.json.
In this case: npm is looking for react 17, while react 16.13 is also a version that is suits >=16.9.0
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: [email protected]
npm ERR! Found: [email protected]
npm ERR! node_modules/react
npm ERR! react@"^16.13.1" from the root project
npm ERR! peer react@">=16.9.0" from @testing-library/[email protected]
npm ERR! node_modules/@testing-library/react-hooks
npm ERR! @testing-library/react-hooks@"3.4.1" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@"17.0.1" from [email protected]
npm ERR! node_modules/react-test-renderer
npm ERR! peer react-test-renderer@">=16.9.0" from @testing-library/[email protected]
npm ERR! node_modules/@testing-library/react-hooks
npm ERR! @testing-library/react-hooks@"3.4.1" from the root project
npm ERR!
npm should be able to resolve the [email protected] peer dependency from @testing-library/[email protected] because [email protected] is a dependency that matches react@>=16.9.0.
I have to downgrade @testing-library/[email protected]
because the peer react-test-renderer@">=16.9.0"
will resolve in react-test-renderer@">=17.0.1"
. This version of react-test-renderer
needs in turn react@"17.0.1"
@RobinWijnant you shouldn't need to do that; but you will need to manually specify react-test-renderer@16
as a dev dep.
Hmm.... yeah, so the react-test-renderer@">=16.9.0"
peer dep resolves to [email protected]
, which requires react@17, and because @testing-library/react-hooks@3
requires react-test-renderer@>=16.9.0
, it resolves to that higher version.
We do aggressively dedupe peerDeps, so if something _else_ were pulling in a lower version of react-test-renderer
, we'd use that instead of 17, but what we don't do is roll back to an earlier version if it ends up bringing in a peer later down the line.
Eg:
a -> PEER(b@>=1)
b@1 -> PEER(c@>=1)
b@2 -> PEER(c@>=2)
c@1 -> PEER(d@>=1)
c@2 -> PEER(d@>=2)
thing -> (a, d@1) <-- this will cause troubles, because a->b@2->c@2->d@2 conflicts with d@1
The only way to resolve this would likely be to build up a full pubgrub style ruleset. We sort of approximate such a thing today, but rely on heuristics and nesting to get out of some of the stickiest situations.
This also highlights the problem with using >=
rather than ^
. We might be able to skirt around the worst hazards by preferring a >=
match which is _also_ within the ^
range, where possible. In that case, the >=16.9.0
would resolve to the same as ^16.9.0
, but be _able_ to dedupe against 17.0.1
if necessary.
Either of these ideas probably merit an RFC though.
Actually, just preferring a ^
match when >=
is used won't do it. Too many packages out there have peer dependencies like webpack@^4.1.0 || ^5.0.3
, and catching every possible iteration won't work out. Eventually, we're always going to have NP-hard territory to venture into.
I don't believe this should be closed. It currently breaks standard NPM7 installs of several major dependencies, such as for example styled-components
:
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: @[email protected]
npm ERR! Found: [email protected]
npm ERR! node_modules/react
npm ERR! dev react@"^16.8.0" from the root project
npm ERR! peer react@">= 16.8.0" from [email protected]
npm ERR! node_modules/styled-components
npm ERR! dev styled-components@"^5.0.0" from the root project
npm ERR! peer styled-components@">= 5" from [email protected]
npm ERR! node_modules/jest-styled-components
npm ERR! jest-styled-components@"^7.0.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@"17.0.1" from [email protected]
npm ERR! node_modules/react-dom
npm ERR! peer react-dom@">= 16.8.0" from [email protected]
npm ERR! node_modules/styled-components
npm ERR! dev styled-components@"^5.0.0" from the root project
npm ERR! 1 more (jest-styled-components)
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.
npm ERR!
npm ERR! See /Users/csvanefalk/.npm/eresolve-report.txt for a full report.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/csvanefalk/.npm/_logs/2020-11-15T08_19_37_425Z-debug.log
I understand that the solution is complex (and I have nothing to contribute myself), but until one is in place it is probably useful to keep this (or a similar) issue open as a reference point for people running into it.
On that note, the above is temporarily resolvable by passing the --legacy-peer-deps
flag.
Seems like you鈥檙e missing a top-level dependency on react-dom (that matches the same minor as react itself). If you fix that, what happens?
@ljharb yes, it works if I add explicit dependencies at the top level like in npm6, but my understanding was that npm7 resolves and installs peer dependencies in a way that meant this was no longer necessary, sorry if I got this wrong: https://github.com/npm/rfcs/blob/latest/implemented/0025-install-peer-deps.md
The problem seems to be that since the peer version of react-dom in this case is >= 16.8.0
(this is true for all my dependencies and sub-dependencies, none of them have a peer dependency on React 15 or 17), npm7 resolves the latest available version (17.0.1 in this case), but then concludes that it is not a match for the peer dependency.
It鈥檚 sometimes no longer necessary, but it鈥檚 still always better to be explicit.