Skip to content

socket-patch --update on a pnpm-installed copy says "managed by npm" and gives an npm command: npm update -g leaves a pnpm global install stale, and npm install …@latest in a pnpm project breaks the next pnpm install --frozen-lockfile #1111

Closed

Description

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

Summary

When socket-patch was installed with pnpm (pnpm add -g @socketsecurity/socket-patch or pnpm add @socketsecurity/socket-patch in a project), socket-patch --update refuses with managed_install and says the binary "is managed by npm". The upgrade command it gives is an npm command, and neither one works for a pnpm install:

  • pnpm global install → npm update -g @socketsecurity/socket-patch. npm's global prefix doesn't hold the package, so npm prints "up to date" and the pnpm copy stays on the old version.
  • pnpm project dependency (new on main) → npm install @socketsecurity/socket-patch@latest. Running it in a pnpm project does update the binary, but it also writes a package-lock.json, bumps package.json to ^4.0.0 and leaves pnpm-lock.yaml on the old version. The next pnpm install --frozen-lockfile (the CI default) then fails with ERR_PNPM_OUTDATED_LOCKFILE. The stray package-lock.json also becomes a second npm-family lock that socket-patch's own hosted/vendored modes will see from then on.

The passive update notifier uses the same hint (crates/socket-patch-cli/src/update_notifier.rs:240), so users see it on ordinary runs whenever a newer release exists.

Impact

Every user who installed socket-patch through pnpm is told to upgrade with a command that either does nothing (global) or breaks their pnpm project's frozen install (project). vlt already gets its own command (vlt install … / vlx …); pnpm doesn't.

Repro (Linux, Node 22, pnpm 9.15.9 / 10.34.6 / 12.10.1, all in scratch dirs)

export PNPM_HOME=$PWD/home/pnpm npm_config_prefix=$PWD/npmprefix PATH=$PWD/home/pnpm:$PWD/home/pnpm/bin:$PATH

# Global
pnpm add -g @socketsecurity/socket-patch@3.3.0
socket-patch --update        # (main binary in place of the published one) → "managed by npm; update it with `npm update -g @socketsecurity/socket-patch`"
npm update -g @socketsecurity/socket-patch   # "up to date"
socket-patch --version       # still 3.3.0

# Project
mkdir proj && cd proj
echo '{"name":"proj","version":"1.0.0","private":true,"dependencies":{"left-pad":"1.3.0"}}' > package.json
pnpm add @socketsecurity/socket-patch@3.3.0
./node_modules/.bin/socket-patch --update   # main → "managed by npm; update it with `npm install @socketsecurity/socket-patch@latest`"
npm install @socketsecurity/socket-patch@latest   # writes package-lock.json, package.json now "^4.0.0", pnpm-lock.yaml still 3.3.0
pnpm install --frozen-lockfile                    # ERR_PNPM_OUTDATED_LOCKFILE

To test main's hint I installed the published 4.0.0 / 3.3.0 package with pnpm and copied main's target/release/socket-patch over the platform binary (node_modules/.pnpm/@socketsecurity+socket-patch-linux-x64-gnu@…/…/socket-patch). The refusal happens before any network I/O.

The commands that do work: pnpm add -g @socketsecurity/socket-patch@latest (global: 3.3.0 → 4.0.0) and pnpm add @socketsecurity/socket-patch@latest (project: 3.3.0 → 4.0.0, and --frozen-lockfile still passes). I checked both on 10.34.6 and 12.10.1.

Expected vs actual

CLI_CONTRACT.md (§ self-update, line 975): "every other channel is refused with that channel's own upgrade command." Expected: a pnpm install is labelled pnpm and pointed at pnpm add -g @socketsecurity/socket-patch@latest (global) or pnpm add @socketsecurity/socket-patch@latest (a project whose root holds pnpm-lock.yaml, or whose binary path runs through node_modules/.pnpm), the same way vlt projects get vlt install ….
Actual: the contract's own table (line 993) sends "a yarn/pnpm global store" to npm update -g, and the code sends pnpm projects to npm install. Neither is pnpm's command. So the table row is the defect, not a documented limitation.

OS × version

OS pnpm layout (canonical exe) hint on main hint on 4.0.0 following the hint
Linux 9.15.9 global global/5/.pnpm/… npm update -g … same no-op, stays 3.3.0 (twice)
Linux 9.15.9 project node_modules/.pnpm/… npm install …@latest npm update -g … ERR_PNPM_OUTDATED_LOCKFILE + stray package-lock.json
Linux 10.34.6 global global/5/.pnpm/… npm update -g … same no-op (twice)
Linux 10.34.6 project npm install …@latest npm update -g … ERR_PNPM_OUTDATED_LOCKFILE (twice)
Linux 12.10.1 global global/v11/<hash>/node_modules/.pnpm/… npm update -g … same no-op
Linux 12.10.1 project npm install …@latest npm update -g … ERR_PNPM_OUTDATED_LOCKFILE

The path logic is OS-independent (%LOCALAPPDATA%\pnpm\global\… on Windows takes the same global branch), but I didn't probe macOS or Windows. 4.0.0 is wrong too (it says npm update -g even for a project install), so this isn't a regression. Main changed the project-install text to npm install …@latest, which is the variant that actively breaks the lockfile.

Suspect code

  • crates/socket-patch-core/src/update/channel.rs:134 (upgrade_hint_for): special-cases vlt / vlx but not pnpm. A node_modules/.pnpm segment in the canonical path, a pnpm-lock.yaml in the holder dir, or a pnpm/global store all identify pnpm.
  • crates/socket-patch-core/src/update/channel.rs:171 (is_global_npm_install) treats the pnpm global store as an npm global.
  • channel_label (channel.rs:~200) reports "npm" for every node_modules install.
  • CLI_CONTRACT.md line 993 (the npm row of the managed-install table).

The same table row also covers a yarn global store. I didn't test yarn or Bun here.

No probe runs (Linux only).


Backlog review — 2026-10-08

Priority: P1 → P2. Self-update prints the wrong package-manager command. This is actionable, but the bad install requires following the incorrect advice.

Activity

  1. mikolalysenko commented on Oct 8, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Triaged: priority:p1 (pnpm). This is a self-update channel bug in update/channel.rs: upgrade_hint_for, is_global_npm_install and channel_label have no pnpm case. CLI_CONTRACT.md's managed-install table row needs to change with it. No open PR covers it yet.


    Generated by Claude Code

  2. added
    v5-blockerMust resolve before v5: public interface/migration or ordinary patch-install-undo failure.
    uxCLI commands, help, diagnostics, output consistency, or actionable recovery instructions.
    compatibilityPublic CLI/JSON, saved state, upgrades, or package-manager compatibility.
    and removed on Oct 8, 2026
  3. mikolalysenko commented on Oct 9, 2026

    @mikolalysenko
    CollaboratorAuthor

    v5 release blocker (P1). The v5 upgrade instruction must use the package manager that installed the CLI. The current npm command is wrong for pnpm and can introduce another lockfile.

    This follows the maintainer's release scope: one normally completing CLI instance, prioritizing valid-lockfile patch/install behavior, compatibility, and actionable CLI UX.

  4. mikolalysenko commented on Oct 9, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Claiming for v5 blocker burn-down (shared root cause: update/channel.rs has no pnpm case, so pnpm installs are labelled npm and given npm commands). Branch: agent/v5-update-pnpm-channel. Claim-ID: 2026-10-09T16:41:47Z-65fd29

  5. added a commit that references this issue on Oct 9, 2026
    f5b7f69
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

    agent:triagedbugSomething isn't workingbughuntFound by a scheduled package-manager bug-hunt agentcompatibilityPublic CLI/JSON, saved state, upgrades, or package-manager compatibility.pm:pnpmpnpmpriority:p1uxCLI commands, help, diagnostics, output consistency, or actionable recovery instructions.v5-blockerMust resolve before v5: public interface/migration or ordinary patch-install-undo failure.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions