Skip to content
Latchkey

Yarn Berry nodeLinker Errors - Fix PnP vs node-modules in CI

Yarn Berry’s nodeLinker setting decides how dependencies are installed: Plug’n’Play (no node_modules), node-modules, or pnpm. CI breaks when the tooling expects one layout but the project is configured for another.

What this error means

Under Yarn Berry, CI either finds an empty/absent node_modules (because PnP is the linker) and tooling cannot resolve modules, or a tool errors out specifically because PnP is active. The fix is to make the linker match what your tooling supports.

Yarn / tool output
# .yarnrc.yml has: nodeLinker: pnp
# a tool that walks node_modules then fails:
Error: Cannot find module 'react'
  (node_modules is empty under Plug'n'Play)
# or a tool that does not understand PnP throws its own resolution error

Common causes

PnP is active but tooling expects node_modules

With nodeLinker: pnp, there is no node_modules - dependencies are resolved via .pnp.cjs. Tools that scan node_modules directly cannot find anything.

The CI config does not match .yarnrc.yml

A workflow assuming a node-modules layout (caching node_modules, running tools unaware of PnP) conflicts with a project set to PnP, or vice versa.

How to fix it

Choose a linker your tooling supports

If your tools need a real node_modules, set the node-modules linker explicitly.

.yarnrc.yml
# .yarnrc.yml
nodeLinker: node-modules

Or make CI PnP-aware

  1. Keep PnP and run scripts via yarn <script> so the PnP runtime is injected.
  2. Use the Yarn SDKs/loader for tools that support PnP (e.g. via yarn dlx @yarnpkg/sdks).
  3. Cache .yarn/cache and .pnp.cjs instead of node_modules under PnP.

How to prevent it

  • Pick a nodeLinker that matches your toolchain and stick to it.
  • Align CI caching with the chosen linker (PnP vs node-modules).
  • Run tools through yarn so PnP resolution is applied.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →