Skip to content

rubnogueira/pnpm-repro-sharedlockfile

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pnpm repro: per-package install prompts to purge node_modules under enableGlobalVirtualStore

Minimal reproduction of a bug where, in a workspace using enableGlobalVirtualStore: true together with per-package lockfiles (sharedWorkspaceLockfile: false + a nested pnpm-workspace.yaml in each package), running pnpm install inside a workspace package — after a successful install at the workspace root — prompts:

? The modules directory at ".../libs/common/node_modules" will be removed and
  reinstalled from scratch. Proceed? (Y/n)

(In a non-TTY/CI shell the same condition surfaces as ERR_PNPM_ABORTED_REMOVE_MODULES_DIR_NO_TTY.)

Layout

.
├── package.json              # private workspace root (no deps)
├── pnpm-workspace.yaml        # packages: [libs/*]; enableGlobalVirtualStore; sharedWorkspaceLockfile: false
└── libs/common
    ├── package.json          # one dep: is-odd
    └── pnpm-workspace.yaml    # makes libs/common ALSO its own workspace root; enableGlobalVirtualStore

libs/common is therefore both a member of the root workspace and its own standalone workspace root (it has its own pnpm-workspace.yaml and gets its own pnpm-lock.yaml). This dual role is what exposes the bug.

Reproduce

./reset.sh                 # remove node_modules + per-project lockfiles
pnpm install               # at the root — succeeds
cd libs/common && pnpm install
# -> prompts to remove & recreate node_modules (or ABORTED_..._NO_TTY in CI)

Root cause

The purge is triggered by an ERR_PNPM_UNEXPECTED_VIRTUAL_STORE mismatch in libs/common/node_modules/.modules.yaml:

Install virtualStoreDir it expects / records
root workspace install records local node_modules/.pnpm
standalone libs/common install wants global <store>/v11/links

Both have GVS enabled, so they should agree. The divergence comes from the post-install build pass:

  1. The install/link step writes .modules.yaml with the correct GVS value virtualStoreDir = <store>/links (set by extendInstallOptions).
  2. A per-project rebuild pass (buildProjects in building/after-install/src/index.ts, run via the recursive rebuild during a workspace install) calls getContext() then rewrites each project's .modules.yaml. Its options come from extendBuildOptions, which — unlike extendInstallOptions — never sets virtualStoreDir = <store>/links for GVS. So getContext falls back to the local node_modules/.pnpm default and the rewrite clobbers the correct value.

The next install inside the package recomputes <store>/links, sees the recorded local .pnpm, and concludes the modules dir is incompatible → purge prompt.

(buildSelectedPkgs in the same file already preserves ctx.modulesFile?.virtualStoreDir ?? ctx.virtualStoreDir; buildProjects does not.)

Fix

Make the build options GVS-aware, symmetric with extendInstallOptions, in building/after-install/src/extendBuildOptions.ts:

if (extendedOpts.enableGlobalVirtualStore && extendedOpts.virtualStoreDir == null) {
  extendedOpts.virtualStoreDir =
    extendedOpts.globalVirtualStoreDir ?? path.join(extendedOpts.storeDir, 'links')
}

With this, the build pass records the same <store>/links the install wrote, both the root and the package record it consistently, and the per-package install no longer prompts to purge.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages