Diagnosing and Fixing Ghost Dependencies and Version Conflicts in Yarn Berry PnP
Learn how to detect ghost dependencies and version mismatches in Yarn Berry’s Plug'n'Play setup and apply targeted fixes using why, resolutions, and patch.
01 Mar 2026, 15:23 UTC

Recognizing the Problem
When running a Yarn Berry project with Plug'n'Play (PnP) enabled, you may encounter a sudden "Module not found" error for a package that you know is installed, or see version‑mismatch warnings that only appear in CI. These symptoms usually point to one of two issues: a ghost dependency (an import that is not declared in package.json) or a version conflict where two packages require incompatible releases of the same library.
Cause and Diagnostic Overview
| Symptom | Likely Cause | First Diagnostic Command |
|---|---|---|
Error: Module not found for lodash (or any valid package) | Ghost dependency: the module is a sub‑dependency of another package but not listed in your package.json | yarn why lodash |
Runtime hook errors or warnings about multiple versions of react | Version conflict: different packages resolve to different releases of the same library | yarn list --pattern react |
| Build passes locally but fails in CI | Environment mismatch: CI expects a physical node_modules folder while PnP does not create one | yarn config info (look for nodeLinker setting) |
Ordered Checks
- Confirm PnP is active – run
yarn config get nodeLinker. Expect outputpnp. If it showsnode-modules, switch to PnP by deletingnode_modulesand.yarn/cachethen runningyarn install. - Trace the offending module – execute
yarn why <module-name>. Examine the tree: if the module appears only under another dependency and not under the rootpackage.json, it is a ghost dependency. - Check for version spread – run
yarn list --pattern <module-name>. If more than one version line appears, note the versions and which dependents request them. - Validate lockfile integrity – run
yarn workspaces focus --all(if using workspaces) or simplyyarn installto ensure the lockfile matches thepackage.json.
Fixes Tied to Findings
Fixing a Ghost Dependency
Once yarn why shows the module is only a sub‑dependency, add it explicitly to your project:
yarn add <module-name>
This writes the package into package.json and updates the .pnp.cjs map, making the import resolvable.
Resolving a Version Conflict
If yarn list reveals multiple versions, decide which version to enforce. Add a resolutions section to the root package.json:
{
"name": "my-project",
"version": "1.0.0",
"resolutions": {
"": "",
"**": ""
}
}
Then run yarn install to regenerate the lockfile with the forced version.
Making a Third‑Party Package PnP‑Compatible
When a dependency fails because it expects a file‑system layout or lacks declared peer dependencies, create a patch:
yarn patch <package-name>
Edit the temporary files to add missing peerDependencies or adjust paths, then save. Yarn will generate a .patch file and apply it on subsequent installs.
Escalation Criteria
- If after adding the missing dependency the error persists, re‑run
yarn whyto verify that the module is now reachable from the root. - If forcing a version with
resolutionsintroduces runtime errors (e.g., missing methods), revert the resolution, consult the upstream libraries’ changelogs, and consider upgrading or downgrading the dependents instead of a blanket force. - When a patch does not apply cleanly or the package updates frequently, consider forking the repository and using a
resolutionspointer to your fork, or discuss upstream compatibility with the maintainers. - If CI continues to fail despite a correct PnP setup, ensure the CI image has Yarn Berry installed and that the
nodeLinkeris set topnp(some CI caches may restore anode_modulesfolder; clear caches before installing).
By following these steps you can turn opaque "Module not found" or version‑mismatch messages into actionable diagnostics, keep your dependency graph explicit, and maintain a stable PnP‑enabled workflow.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.