npm's dependency resolver was designed by someone who clearly never had to debug this shit at 3am. Install one UI library that worked fine yesterday, suddenly your entire project won't build because "peer dependency conflicts."
npm's algorithm tries to flatten dependency trees but fails spectacularly when peer deps conflict.
Real Example from 2025:
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^17.0.0" from some-ui-library@1.2.3
npm ERR! node_modules/some-ui-library
npm ERR! some-ui-library@"^1.2.3" from the root project
npm ERR! peer react@"^18.0.0" from another-component@2.1.0
This error message is telling you that some-ui-library
expects React 17, but another-component
expects React 18, and npm can't reconcile this conflict.
Peer Dependencies - The Root of All Evil
Peer dependencies are npm's way of saying "you figure it out." Package maintainers specify what version of React they think they need, but don't actually install it. Your project has to provide the right version.
The official npm docs explain this poorly, but this dev.to guide breaks down why this design is fundamentally flawed.
Would be fine if library maintainers updated their shit when new versions drop. But they don't. React 18 came out in March 2022 and I'm STILL finding packages that declare "react": "^17.0.0"
as a peer dep. It's 2025. Get your fucking act together.
Check npm trends and you'll see how many packages are still stuck on ancient peer deps. The React ecosystem is full of libraries that haven't been updated in years.
Version Range Clusterfuck
You know how lodash v3 and lodash v4 are completely different? Well npm doesn't. One package wants "lodash": "^4.0.0"
and another wants "lodash": "^3.10.1"
and npm just gives up.
The semver spec was supposed to prevent this, but in practice it's broken. Check bundlephobia to see how many different versions are floating around.
Semver ranges were supposed to solve this but actually make it worse. Updated our TypeScript config yesterday and suddenly three dev tools stopped working because they all had different opinions about what version they needed.
Transitive Dependency Hell
The absolute worst: conflicts from packages you never even installed. You add some chart library, it depends on some utility lib, which depends on React 17. Your project uses React 18. Now your build is broken because of some package buried three levels deep that you've never heard of.
Why 2025 Made Everything Worse
React 19 dropped in December 2024 and broke half the ecosystem. Every UI library I actually use is still on React 17/18 peer deps. Want to try React's new concurrent features? Good luck - MUI hasn't updated, Chakra's dragging their feet, and don't even get me started on all the random component libraries.
TypeScript 5.x fucked everything too. They changed how types get resolved and suddenly ESLint plugins, testing libraries, build tools - everything just stopped working. "Minor" version updates my ass.
TypeScript breaking changes happen way more often than they admit.
Oh and ESM vs CommonJS is still a disaster. Import some package expecting it to work, get ERR_REQUIRE_ESM
and realize you just wasted 20 minutes because the docs didn't mention it's ESM-only.
The Node.js documentation explains dual packages but most library authors don't give a shit about backwards compatibility.
Reading the Error Messages
npm's error messages are written by people who hate developers, but they follow patterns once you learn to decode the bullshit:
npm ERR! ERESOLVE could not resolve
npm ERR!
npm ERR! While resolving: my-project@1.0.0
npm ERR! Found: react@18.2.0
npm ERR! node_modules/react
npm ERR! react@"^18.2.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^17.0.0" from problematic-package@1.2.3
This is telling you:
- "While resolving: my-project@1.0.0" - npm is trying to install dependencies for your root project
- "Found: react@18.2.0" - Your project has React 18 installed
- "Could not resolve dependency: peer react@"^17.0.0"" - But
problematic-package
expects React 17
So you've got three options: downgrade React (fuck that), upgrade the package (doesn't exist), or force npm to use what you want with overrides.
Real Cost of This Bullshit
MUI v5 migration took us 3 weeks. Not because the code was hard - because dependency resolution kept breaking in weird ways. Business kept asking why the feature was late while I'm explaining that our button library has opinions about React versions.
Lost a whole weekend once because some security audit tool flagged lodash vulnerabilities, but updating lodash broke our build tools, so we were stuck with old vulnerable versions until someone updated their peer deps.
And don't get me started on "works on my machine" - when everyone has slightly different node_modules because they installed packages at different times, nothing fucking works consistently.