Overview
This skill is used to handle pnpm-related installation, updates, workspace command replacement, Windows/PowerShell failures, and global package recovery. It focuses on covering ERR_PNPM_UNEXPECTED_VIRTUAL_STORE、PNPM_HOME and global dependency tree misalignment, Corepack managing pnpm, and pnpm runtime confusion after NVM Desktop switches Node.
The goal is not to recount the incident process, but to give future-agent an executable decision path: first identify who manages pnpm, where the global area is, where the store is, and where the virtual store points, then decide whether to rebuild the dependency tree, fix the configuration, or switch back to the correct Node/pnpm management chain.
pnpm 12 breaking-generation premise: pnpm 12 (Rust native version) has four semantic tightenings regarding configuration read locations, build approval, and supply chain verification, and corepack can no longer install pnpm from then on. Whenever pnpm version determination, upgrades, or CI installation are involved, first read references/pnpm12-migration.md and references/corepack-eol-and-shim.md。
Low-Model Execution Contract
Low-tier models must execute global upgrade/approval tasks as a "step-by-step checklist" and must not skip steps based on the title or memory. Copy the relevant specific commands only from references/global-upgrade-checklist.md , and obey the following hard gates:
- First complete the runtime inventory; if any command exits non-zero, a path is empty, or results contradict, immediately
STOP, and do not continue upgrading. - Execute only one checklist step at a time; record the command, exit code, key output, and next step for each step. Do not combine multiple upgrade batches, rebuilds, or verification commands into one.
- When encountering interactive approval, select only packages whose purpose has been confirmed in the checklist; if uncertain, keep them unapproved and
STOP. It is forbidden to treat--allas a quick fix. - When
MSB8040, node-gyp, MSBuild, timeout, or no output appears, immediately stop the current package, preserve the written policy and logs, do not expand the approval scope, and do not retry the entire batch. - Only when all four conclusions have evidence can completion be reported: package upgrade, approval policy written, build script executed, CLI runnable. If any item is missing, only "partially complete/pending" can be reported.
Global write operations must also satisfy two authorization gates:
- When the user has not explicitly authorized global upgrade, approval, rebuild, or deletion, execute only the read-only inventory in Section 1 of the reference checklist, then stop and request authorization.
- Before starting each section, confirm that the ledger exit code of the previous section is
0; if the previous section failed, was interrupted, or was not executed, do not jump to subsequent sections.
When to Use
- The user requests to install, update, delete, or rebuild pnpm dependencies or global packages.
- The user wants to replace
npm、npx、yarncommands with pnpm syntax. - The pnpm error contains keywords such as
ERR_PNPM_UNEXPECTED_VIRTUAL_STORE、virtual-store-dir、store-dir、PNPM_HOME, global root, global bin, etc. - Under Windows or PowerShell, pnpm commands are abnormal, global commands cannot be found, or global package upgrades fail.
- Corepack manages pnpm, or after NVM Desktop switches Node, the pnpm version, path, and global area are inconsistent.
- After upgrading to pnpm 12, encountering
ERR_PNPM_IGNORED_BUILDS、allowBuilds、blockExoticSubdeps、ERR_PNPM_MISSING_TARBALL_INTEGRITY、.npmrcsettings not taking effect,pnpm.overridesbeing ignored, or needing to migrate the corepack step in the workflow. - In a pnpm workspace, it is necessary to determine whether a command should be executed in the root directory, a subpackage directory, or via
--filter.
When Not to Use
- The task is unrelated to pnpm and is only a general Node.js, TypeScript, Git, or framework issue.
- The user explicitly requested to use another package manager, and there is no context of migrating to pnpm.
- The current project has no pnpm configuration, and the user has not requested introducing pnpm. Do not proactively change the package manager.
- It only explains JavaScript syntax, Node APIs, or business code logic, and does not involve dependency management.
Core Model
Before handling pnpm failures, these concepts must be distinguished:
PNPM_HOME: the location where pnpm places the global executable entry, which usually should appear inPATH. It is not the real global dependency installation tree, nor the store.pnpm root -g: the global packages'node_modulesroot directory, that is, the location of the global dependency tree, which can be called<pnpm-global-node-modules>; its parent directory is the global area directory, usually containing globalpackage.jsonandpnpm-lock.yaml。pnpm bin -g: the directory where global command shims/bins are located, which may be equal to or close toPNPM_HOME, but must be confirmed with commands.store-dir/pnpm store path: the pnpm content-addressable store, which stores the package content cache and can be called<store-dir>。virtual-store-dir: the virtual store directory inside the project or global dependency tree, whose default is usuallynode_modules/.pnpm. It describes the dependency tree layout and is not equal tostore-dir。
Decision principles:
store-diris the package content cache,virtual-store-diris the link layout directory in a certain dependency tree.ERR_PNPM_UNEXPECTED_VIRTUAL_STOREusually indicates that the existingnode_modules's.modules.yamlrecords are inconsistent with the virtual store location expected by the current pnpm.- If the error occurs in
pnpm add -g、pnpm update -g、pnpm i -g, global command upgrades, or global package list operations, handle it first as a global scenario. - In the global scenario, prioritize rebuilding the global dependency tree; do not immediately change the global
.npmrcor global pnpm configuration.
First Checks
In Windows/PowerShell, first collect these pieces of evidence:
where.exe node
where.exe pnpm
where.exe corepack
node -v
pnpm -v
corepack --version
pnpm config get global-dir
pnpm config get store-dir
pnpm config get virtual-store-dir
pnpm store path
pnpm root -g
pnpm bin -g
If it is a project-internal issue, then also add:
pnpm config list
pnpm config list --location project
pnpm config list --location global
pnpm install --lockfile-only may write to pnpm-lock.yaml. This command is executed only when the user allows updating the lockfile or when lockfile resolution needs to be verified; do not treat it as a purely read-only evidence collection command.
When checking node_modules/.modules.yaml , read only the key fields:storeDir、virtualStoreDir、layoutVersion、packageManager. Do not treat the entire file as a configuration file that needs manual repair.
Decision Path
-
Determine who manages pnpm:
corepack pnpm --versionis available and the project depends on Corepack: prioritize management by Corepack.where.exe pnpmpoints to a certain Node installation or Corepack shim: continue checkingwhere.exe nodeand the version.- pnpm comes from an independent installer or the system package manager: handle it according to the corresponding installation source, and do not mix in global npm installation.
-
Determine the scope of the error:
- With
-gor involving global commands: global scenario. - Execute in the project root directory or subpackage
pnpm install: project/workspace scenario. - Only a certain package script fails: first confirm whether the script actually calls pnpm or reads the pnpm path.
- With
-
Determine whether it is virtual store misalignment:
- The error contains
ERR_PNPM_UNEXPECTED_VIRTUAL_STORE。 .modules.yamlinvirtualStoreDirbeing inconsistent with the current configuration or current path.- It appears after switching Node, pnpm version, configuration, or migrating directories.
- The error contains
-
Choose a recovery strategy:
- Global scenario: back up the global dependency tree metadata and rebuild the global area.
- Project scenario: prioritize deleting and rebuilding the current project's
node_modules, and do not change global configuration to bypass it. - Configuration pollution scenario: remove the unreasonable global
virtual-store-dir, and if necessary write a relative path at the project level and explain why.
Windows Global Virtual Store Recovery
When encountering a global ERR_PNPM_UNEXPECTED_VIRTUAL_STORE , handle it in this order.
First back up the global metadata:
$globalNodeModules = pnpm root -g
$globalDir = Split-Path -Parent $globalNodeModules
Copy-Item -LiteralPath "$globalDir\package.json" -Destination "$globalDir\package.json.bak" -ErrorAction SilentlyContinue
Copy-Item -LiteralPath "$globalDir\pnpm-lock.yaml" -Destination "$globalDir\pnpm-lock.yaml.bak" -ErrorAction SilentlyContinue
Copy-Item -LiteralPath "$globalNodeModules\.modules.yaml" -Destination "$globalDir\.modules.yaml.bak" -ErrorAction SilentlyContinue
Then rebuild the global dependency tree:
pnpm i -g
If the current environment has no TTY, and pnpm i -g cannot continue due to an interactive prompt, you can temporarily set it only for this one command CI=true:
$hadCI = Test-Path Env:CI
$previousCI = $env:CI
try {
$env:CI = "true"
pnpm i -g
}
finally {
if ($hadCI) {
$env:CI = $previousCI
}
else {
Remove-Item Env:CI -ErrorAction SilentlyContinue
}
}
If it still fails, then check:
pnpm config get virtual-store-dir
pnpm config list --location global
pnpm root -g
pnpm store path
Do not write an absolute virtual-store-dir into the global .npmrc or global pnpm config to suppress the error. An absolute virtual store couples different Node versions, different users, and different global areas to the same layout path, making recurrence more likely when switching Node or migrating directories later.
NVM Desktop + Corepack Rules (version domain separation)
The core risk of Windows + NVM Desktop + Corepack is:node、corepack、pnpm may come from different Node versions or different shim directories. After switching Node or changing the pnpm version, verify the path and version first, then rebuild the global area.
Commands that must be checked:
where.exe node
where.exe pnpm
where.exe corepack
node -v
pnpm -v
corepack --version
pnpm root -g
pnpm bin -g
pnpm store path
pnpm config get global-dir
pnpm config get store-dir
pnpm config get virtual-store-dir
Rules are domain-separated by the target pnpm major version; first confirm package.json 's packageManager field before acting:
pnpm ≥12 (target version is the new version):
- The corepack route is fully disabled:
corepack installcannot install pnpm 12 (a mechanistic dead end, not a version lag);corepack enablein workflow or preinstall hooks is guaranteed-to-explode dead code; delete it on sight. - For global upgrades use
pnpm self-update(a corepack-managed pnpm will refuse self-update, so you must first break away from corepack),npm i -g pnpm@latest-12or the native binary; for the specific route and shim resurrection prevention, seereferences/corepack-eol-and-shim.md。 - The pnpm 12 native exe does not depend on Node; switching Node does not affect the global pnpm version; but the pnpm entry in PATH must be unique and have the correct priority.
pnpm ≤11 (legacy repositories):
- If the project uses Corepack to manage pnpm, do not treat
npm i -g pnpmorpnpm add -g pnpmas the preferred way to upgrade the pnpm itself; prefer Corepack activation or preparing the target version. - When the upgrade target crosses to 12, migrate according to
references/corepack-eol-and-shim.md's native installation route; do not try to make corepack cross generations.
General:
- After switching Node, the global package area and shims may need to be reinstalled or rebuilt. First make
where.exe node、where.exe pnpm、where.exe corepackpoint to the same expected chain, then runpnpm i -g。 - Do not mix multiple sources to install pnpm. When multiple
where.exe pnpmresults appear, explain the path priority first, then decide which one to clean up. ~\.nvmd\binA pnpm shim resurrected in a node manager shim directory such asreferences/corepack-eol-and-shim.mdSection 3.
Command Mapping
Common replacements:
| npm/yarn/npx | pnpm |
|---|---|
npm install |
pnpm install |
npm install <pkg> |
pnpm add <pkg> |
npm install -D <pkg> |
pnpm add -D <pkg> |
npm uninstall <pkg> |
pnpm remove <pkg> |
npm update <pkg> |
pnpm update <pkg> |
npm run <script> |
pnpm run <script> or pnpm <script> |
npx <bin> |
pnpm dlx <bin> |
yarn add <pkg> |
pnpm add <pkg> |
yarn remove <pkg> |
pnpm remove <pkg> |
yarn why <pkg> |
pnpm why <pkg> |
Global commands:
pnpm add -g <pkg>
pnpm update -g <pkg>
pnpm remove -g <pkg>
pnpm list -g --depth 0
Note:pnpm add -g pnpm is not the default answer for upgrading the pnpm itself. First confirm the pnpm management method and the target major version (for the corepack scenario, see the version domain separation rules above; for the pnpm 12 scenario, see references/corepack-eol-and-shim.md)。
Global Upgrade Policy
For global upgrades, first inventory the runtime, registry, global-dir, store-dir, packages to be upgraded, and scripts awaiting approval; do not treat a single command as complete acceptance.
- For daily upgrades, it is forbidden to use
pnpm up -L -gto scan and upgrade all global packages; group by purpose and then usepnpm update -g --latest <packages>, recording the exit code, version changes, and warnings separately for each batch. - Upgrade the package first, then handle the build script approval separately. An updated package version does not mean install/postinstall has been executed, nor does it mean the CLI is already runnable.
pnpm approve-builds -gYou must interactively select the confirmed minimal allowlist; it is forbidden to use--allas a default or failure fallback. Packages whose purpose is unconfirmed remain unapproved.- Record upgrade, approval, build, and runtime verification separately; when a stage fails, stop expanding the scope, and do not use later success to mask an earlier stage's failure.
For specific package grouping, approval candidates, backup, acceptance, and single-package rebuild commands, see references/global-upgrade-checklist.md。
Native Module Stop-Loss
When you see node-gyp、MSBuild、MSB8040 or a native compilation failure, first record the failing package, exit code, missing components, and the approval policy already written, then stop continuing the build or expanding the allowlist.
node-ptyFailures of native modules such as these are toolchain or platform issues, and must not be bypassed by approving more packages, hand-editing.modules.yaml, writing an absolutevirtual-store-dir, or deleting the global dependency tree.koffi、onnxruntime-nodePackages such as these must also have their actual functional requirements and compilation toolchain confirmed first; "can approve" does not mean "should approve".- A single-package rebuild is used to locate the sticking point; handle only one package at a time, and record the start/end time, exit code, and last output. If there is no new output for about 30 seconds, stop that package and mark it as a candidate sticking point; do not keep waiting blindly or immediately expand the approval scope.
Approval Policy Persistence
approve-builds The policy write and the build result are two independent facts. After the command exits non-zero or is interrupted, you must still check the global pnpm-workspace.yaml:
onlyBuiltDependenciescontains only the packages explicitly approved this time and backed by a purpose;ignoredBuiltDependenciesretains explicitly deferred items.- First record whether the policy file has been persisted, then determine whether the script executed successfully; you cannot claim the build is complete just because the policy has been written.
- Do not hand-write
.modules.yaml, and do not execute a global build policy override beyondpnpm approve-builds.
Interrupted Run Closure
When any upgrade or approval command is interrupted, times out, or exits non-zero, you must output four independent conclusions: whether the package upgrade succeeded, whether the approval policy was written, whether the build script executed successfully, and whether the core CLI is runnable. Record the exit code, completed packages, remaining scripts, and next steps; before the specific root cause is fixed, do not retry the entire batch, and do not use --all as a fallback.
Workspace Rules
- First confirm whether the current directory is the workspace root and whether
pnpm-workspace.yaml。 - When adding a dependency to the workspace at the root directory, specify the target package:
pnpm --filter <package-name> add <dependency>
pnpm --filter <package-name> add -D <dependency>
- When the root package genuinely needs the dependency, use
-w:
pnpm add -w -D <dependency>
- When executing scripts, prefer
--filterto precisely constrain the scope:
pnpm --filter <package-name> build
pnpm --filter <package-name> test
- When unsure of the target package, ask the user first, or read the workspace manifest and the relevant
package.json. Do not arbitrarily install runtime dependencies at the workspace root. - Do not generalize one project's
virtual-store-direxperience to the entire workspace. When customization is genuinely needed, only project-level relative paths are allowed, for example:
virtual-store-dir=.pnpm
and explain why the default node_modules/.pnpm does not apply.
Safety Rules
- Before fixing, back up the
package.json、pnpm-lock.yamlunder global-dir, as well as thepnpm root -gunder the directory returned by.modules.yaml。 - Do not hand-write large blocks of
.modules.yamlcontent; it is a state file generated by pnpm, and should preferably be restored by rebuilding the dependency tree. - It is not recommended to write an absolute
virtual-store-dirinto the global.npmrcor the global pnpm configuration. - If the project genuinely needs
virtual-store-dir, use only project-level relative paths, and clearly state the reason. - Do not use npm global installation, Corepack, and pnpm self-update to manage the same pnpm instance at the same time.
- On Windows, prefer using
where.exeto check the actual command resolution and avoid confusion from PowerShell aliases or shims. - Before deleting
node_modulesor the global dependency tree, first confirm that the path is<project-root>\node_modulesorpnpm root -gthe globalnode_modulesreturned by pnpm root -g, and do not recursively delete ambiguous variables. - In a non-TTY environment, if you need to skip interaction, only temporarily set
pnpm i -gfor a singleCI=trueand do not permanently pollute the shell environment.
Verification Checklist
After the fix is complete, verify at least:
pnpm list -g --depth 0
pnpm root -g
pnpm bin -g
pnpm store path
pnpm config get virtual-store-dir
For the specific commands for global upgrade or post-approval, and the four independent conclusion templates, see references/global-upgrade-checklist.md。
Then rerun the originally failing command. For example:
pnpm add -g <pkg>
pnpm update -g <pkg>
<original-failing-command>
Closure criteria:
pnpm list -g --depth 0can list global packages.- The originally failing command no longer reports
ERR_PNPM_UNEXPECTED_VIRTUAL_STORE。 PNPM_HOME、pnpm bin -g、pnpm root -g、pnpm store pathcan be explained clearly and without mutual confusion.- There is no unreasonable absolute
virtual-store-dir。 - If project-level configuration was changed, the configuration uses relative paths and the reason is documented.
Common Mistakes
- Treat
store-dirasvirtual-store-dir, or treatpnpm store pathas the global dependency installation directory. - Treat
pnpm root -gas global-dir; it returns the globalnode_modules,globalpackage.jsonandpnpm-lock.yamlis in its parent directory. - If you see
ERR_PNPM_UNEXPECTED_VIRTUAL_STOREfirst change the globalvirtual-store-dir。 - When pnpm is managed by Corepack, using
npm i -g pnpmto override the shim causeswhere.exe pnpmto point to confusion. - Under pnpm 12, attempting to use corepack to install or upgrade pnpm (a mechanistic dead end), or retaining the
corepack enablestep in workflow / preinstall. - Under pnpm 12, continuing to put settings in
.npmrcor in package.json'spnpmfield—migrate only topnpm-workspace.yaml, otherwise it is silently ignored (seereferences/pnpm12-migration.mdSection 4). - Under pnpm 12, using
onlyBuiltDependenciesto authorize build scripts—it no longer takes effect; the authorization table isallowBuilds。 - After switching Node in NVM Desktop, only look at
node -v, notwhere.exe node、where.exe pnpm、where.exe corepack。 - Delete the global dependency tree without backing up global metadata.
- Permanently set
CI=truein a non-TTY environment, affecting the behavior of subsequent commands. - In the workspace root directory, add dependencies directly without
--filteror-w. - Write a machine's absolute path into distributable skill documents, project templates, or global configuration.
Future Expansion
This skill should remain simple and scalable over the long term:
- When adding pnpm conventions, incident takeaways, or platform difference notes, put them first in
references/, and keep only the stable decision path in the main text. - Only add
scripts/orfallback/。 - new scripts when reusable, deterministic check logic exists. When adding scripts, they must run from the perspective of the skill installation directory and must not depend on locations outside the installation directory.
- Extended content must not reference non-migratable internal evidence, personal information, machine-specific absolute paths, or environment-specific process paths.
- Externally distributed content should only contain migratable rules, placeholder paths, and verifiable commands.