ERR_PNPM_PEER_DEP_ISSUES during CI install: enforce strict peer checks or bypass them in a monorepo?
0 reputation · 15 Jun 2020, 07:07 UTC
0 reputation · 15 Jun 2020, 07:07 UTC
In a pnpm monorepo (workspace with several child packages, pnpm v8 assumed), the install step in CI aborts with ERR_PNPM_PEER_DEP_ISSUES, reporting unmet peer dependencies for a shared library consumed by multiple workspace packages. The deployment pipeline fails at this point, and the lockfile is committed and up to date.
The unresolved decision is how to treat this failure class. Enforcing strict peer-dependency resolution keeps installs safe but blocks the pipeline whenever a transitive dependency declares a peer range that the workspace does not satisfy exactly. Bypassing the check (for example via --no-strict-peer-requirements or a .npmrc setting) unblocks installation, but the peer dependency may then be genuinely absent at runtime, producing crashes that are hard to trace back to the install step. There is also uncertainty about whether peer-dependency strictness changed between pnpm major versions, which could explain why a previously green pipeline started failing.
Another open point is scope: should the override apply globally to the whole workspace, or only to the specific packages whose peers are known-optional?
Specifically: what criteria determine whether ERR_PNPM_PEER_DEP_ISSUES indicates a real missing dependency versus an overly strict peer range declaration? Is a per-package override in package.json (pnpm.peerDependencyRules) preferable to a global flag, and what are the trade-offs? How can one verify after a bypassed install that no required peer is actually missing at runtime?
To resolve ERR_PNPM_PEER_DEP_ISSUES in a pnpm v8 monorepo, you should avoid global bypass flags in CI and instead use pnpm.peerDependencyRules in the root package.json. This allows you to selectively ignore specific version mismatches without disabling the safety checks for the rest of your dependency graph.
The distinction depends on whether the library actually executes code from the missing peer at runtime:
^1.0.0, but you have 1.1.0 installed. If the API is compatible, this is a range mismatch.react as a peer, but react is not installed anywhere in the dependency chain of the consuming package. This will likely cause a Module not found error at runtime.Rather than using --no-strict-peer-requirements, add a ruleset to your root package.json. This documents the decision and ensures it is version-controlled.
{
"pnpm": {
"peerDependencyRules": {
"ignoreMissing": [
"optional-peer-package"
],
"allowAny": [
"strict-package-with-wrong-range"
]
}
}
}
| Method | Pros | Cons |
|---|---|---|
Global Flag (.npmrc) |
Instant CI fix; low effort. | Hides critical missing dependencies; risks runtime crashes. |
peerDependencyRules |
Explicit; maintains safety for other packages. | Requires manual updates when dependencies change. |
To verify that a bypassed peer is not actually missing, use the following scoped commands:
pnpm why <peer-package-name> to see if the dependency exists anywhere in the graph for the affected package.pnpm list to confirm the resolved versions match the expected runtime environment.Diagnostic Note: Does the error report a missing dependency or a version mismatch? If it is a missing dependency for a package you know is optional, ignoreMissing is the correct path; if it is a version mismatch, allowAny or updating the dependency is required.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.