Back to core workflows Fix dependency resolution Tune package metadata Jump to monorepo patterns

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 (retain workspaces array for cross-tool compatibility)
  • .npmrc (recommended: auto-install-peers=true, strict-peer-dependencies=true)
  • Updated internal package.json dependencies/devDependencies using the workspace: 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+.