Skip to content

Vendored pnpm 10.5+ with overrides: in pnpm-workspace.yaml: the new package.json pnpm.overrides shadows the user's overrides, so frozen installs fail and a re-lock drops them #360

Description

[agent] Found by the scheduled pnpm bug-hunt routine (ledger #303).

Summary

On pnpm 10.5 and later, overrides: can live in pnpm-workspace.yaml. When a project keeps its overrides there, vendor (and scan / get --mode vendored) adds the vendored file: override to that block. It also creates a brand-new pnpm.overrides object in package.json, a back-compat copy kept for pnpm 9/10 since #174. On pnpm 10, a pnpm.overrides field in package.json replaces the workspace-file overrides instead of merging with them. So the effective override set becomes {left-pad@1.3.0: file:…} alone, while the rewritten lock records the user's overrides plus ours.

vendor reports success and vex attests not_affected, but:

  • every pnpm install --frozen-lockfile (CI, fresh clone, or the same checkout) fails with ERR_PNPM_LOCKFILE_CONFIG_MISMATCH.
  • a plain pnpm install "fixes" this by re-locking without the user's overrides, which silently drops them. That can be a security pin, since overrides are commonly used for exactly that.

pnpm 11+ is unaffected, because it doesn't read the package.json pnpm field.

Repro (pnpm 10.34.5, Linux)

mkdir p && cd p
echo '{"name":"p","version":"0.0.0","private":true,"dependencies":{"left-pad":"1.3.0"}}' > package.json
printf "packages:\n  - '.'\noverrides:\n  is-number: 6.0.0\n" > pnpm-workspace.yaml
pnpm install                       # lock records overrides: {is-number: 6.0.0}
# stage a .socket/manifest.json + blobs for pkg:npm/left-pad@1.3.0 (hand-staged, as in tests/e2e_vendor_pnpm_build.rs)
socket-patch vendor --offline --json   # status: success, action: applied
cat package.json                   # NEW: "pnpm": {"overrides": {"left-pad@1.3.0": "file:.socket/vendor/npm/<uuid>/left-pad-1.3.0.tgz"}}
cat pnpm-workspace.yaml            # overrides: is-number: 6.0.0 + left-pad@1.3.0: file:…
# fresh checkout of the committable files, empty store:
pnpm install --frozen-lockfile --offline
#  ERR_PNPM_LOCKFILE_CONFIG_MISMATCH  Cannot proceed with the frozen installation. The current "overrides" configuration doesn't match the value found in the lockfile
socket-patch vex --offline --output v.json   # exit 0, not_affected
pnpm install --no-frozen-lockfile --offline
sed -n '/^overrides/,/^$/p' pnpm-lock.yaml
# overrides:
#   left-pad@1.3.0: file:.socket/vendor/npm/<uuid>/left-pad-1.3.0.tgz      <- is-number: 6.0.0 is gone

Expected vs actual

  • Expected: docs/ecosystems.md (vendored npm row) and fix(vendor): write pnpm overrides to pnpm-workspace.yaml for pnpm >= 11 #174 promise that the vendored lock plus overrides install with a cold pnpm install --frozen-lockfile --offline from the committable files, and that user overrides are preserved (a conflicting one is refused with vendor_override_conflict, per CLI_CONTRACT.md).
  • Actual: vendoring succeeds, but the committable state can't be frozen-installed on pnpm 10.5+. The only remedy pnpm offers (a re-lock) deletes the user's overrides.

Matrix (Linux, current main f6b7fb9)

pnpm user overrides in pnpm-workspace.yaml vendor fresh --frozen-lockfile --offline
10.0.0 yes (pnpm 10.0 ignores them) success pass
10.5.2 yes success ERR_PNPM_LOCKFILE_CONFIG_MISMATCH
10.12.1 yes success ERR_PNPM_LOCKFILE_CONFIG_MISMATCH
10.34.5 yes success ERR_PNPM_LOCKFILE_CONFIG_MISMATCH (reproduced 3×)
11.27.0 yes success pass
12.8.1 yes success pass
10.34.5 no workspace overrides success pass

Released 4.0.0 behaves the same (not a v5 regression). This is config logic, not OS-specific.

Suspect code

crates/socket-patch-core/src/vendor/pnpm_lock.rs:1585 (apply_pkg_override) always creates pnpm.overrides in package.json. When pnpm-workspace.yaml already carries a top-level overrides: block (see ws_overrides_section, :1667, and apply_workspace_override, :1735), the package.json copy should be skipped, because on pnpm 10.5+ it shadows the workspace block. The alternative is to copy the user's workspace overrides into it, but that doubles the surface.

Activity

  1. mikolalysenko commented on Sep 30, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Triaged priority:p1 (pnpm). No shared root cause with other open issues: vendor/pnpm_lock.rs::apply_pkg_override always creates a package.json pnpm.overrides back-compat copy, even when pnpm-workspace.yaml already has overrides:. No open or merged PR addresses it.


    Generated by Claude Code

  2. mikolalysenko commented on Oct 1, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Re-triage from the pnpm bug-hunt routine (ledger #303): this still reproduces on main 2463257 (after #277), 2 of 2 runs on pnpm 10.34.5 (Linux). I used the v5 path, scan --mode vendored against a mock patch API: it exits 0 with status: success, and package.json gains a new pnpm.overrides (left-pad@1.3.0: file:.socket/vendor/npm/<uuid>/left-pad-1.3.0.tgz) next to the workspace overrides: block. A fresh checkout of the committable files (package.json, pnpm-lock.yaml, pnpm-workspace.yaml, .socket/) then fails pnpm install --frozen-lockfile --offline with ERR_PNPM_LOCKFILE_CONFIG_MISMATCH.


    Generated by Claude Code

  3. mikolalysenko commented on Oct 4, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Claiming this issue (cluster of one). Root cause: vendored pnpm always writes a back-compat package.json pnpm.overrides copy, even when the lock shows that pnpm reads the overrides from pnpm-workspace.yaml. Branch: agent/fix-pnpm-workspace-overrides-shadow. Claim-ID: 2026-10-04T13:21:10Z-c140b9


    Generated by Claude Code

  4. mikolalysenko commented on Oct 4, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Draft fix PR: #785


    Generated by Claude Code

  5. added a commit that references this issue on Oct 4, 2026
    caaea02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions