Migrating from Yarn 1 to pnpm Workspaces
🚨 Exact Symptom
ERR_PNPM_WORKSPACE_PKG_NOT_FOUND or workspace:* protocol resolution failure during pnpm install.
🔍 Root Cause Analysis
Yarn 1 relies on implicit workspace resolution via the workspaces field in package.json and flat node_modules hoisting. pnpm enforces strict dependency isolation using a content-addressable store and requires explicit workspace:* protocol declarations for internal packages. Directly migrating without converting internal dependency references or defining a pnpm-workspace.yaml file causes pnpm's resolver to fail when parsing legacy yarn.lock structures or bare version strings. Understanding these architectural differences is critical when navigating Core JavaScript Package Workflows.
🛠️ Resolution & CLI Recovery Steps
Step 1: Initialize pnpm Workspace Configuration
# pnpm-workspace.yaml (monorepo root)
packages:
- 'packages/*'
- 'apps/*'
Prevention: Always define explicit glob patterns to prevent pnpm from scanning unintended directories like node_modules or build artifacts. For advanced topology rules and package scoping, consult the Workspace Configuration Deep Dive.
Step 2: Update Internal Cross-Package Dependencies
Replace all internal package.json dependency references across the monorepo:
// BEFORE (Yarn 1)
"@scope/pkg-a": "1.0.0" // or "file:../pkg-a"
// AFTER (pnpm)
"@scope/pkg-a": "workspace:*" // or "workspace:^"
Prevention: Use pnpm's built-in workspace protocol to guarantee symlink resolution and prevent version drift during local development.
Step 3: Remove Legacy Yarn Artifacts and Install
rm yarn.lock && rm -rf node_modules && pnpm install
Prevention: Never commit yarn.lock alongside pnpm-lock.yaml. Configure .gitignore to explicitly exclude legacy lockfiles and stale caches.
Step 4: Validate Workspace Topology & Dependency Graph
pnpm ls -r --depth=0
pnpm why <package-name>
Prevention: Run pnpm install --frozen-lockfile in CI pipelines to catch unresolved workspace dependencies before deployment.
⚙️ Required Configuration Checklist
pnpm-workspace.yaml(primary package discovery manifest)- Root
package.json(retainworkspacesarray for cross-tool compatibility) .npmrc(recommended:auto-install-peers=true,strict-peer-dependencies=true)- Updated internal
package.jsondependencies/devDependenciesusing theworkspace:protocol
❓ Troubleshooting FAQ
Q: Can pnpm automatically convert a Yarn 1 lockfile to pnpm-lock.yaml?
A: No. pnpm does not support direct yarn.lock conversion. You must delete yarn.lock, update internal dependencies to the workspace:* protocol, and run pnpm install to generate a fresh pnpm-lock.yaml.
Q: Why does pnpm throw ERR_PNPM_WORKSPACE_PKG_NOT_FOUND after migration?
A: This occurs when internal dependencies still reference bare version strings or file: paths instead of the explicit workspace:* protocol required by pnpm's strict resolver.
Q: How do I handle shared devDependencies across pnpm workspaces?
A: Define shared tooling (e.g., TypeScript, ESLint) in the root package.json and use pnpm's workspace protocol or peer dependency hoisting via .npmrc to avoid duplication while maintaining strict isolation.
Q: Is the workspaces field in package.json still required for pnpm?
A: Yes, but it's secondary. pnpm primarily relies on pnpm-workspace.yaml for package discovery. Keeping the workspaces field in package.json ensures compatibility with other tooling like npm or Yarn v3+.