Skip to content

socket-patch --update on a yarn-classic-installed copy says "managed by npm": npm update -g leaves a yarn global add install stale, and a yarn project is told to run npm install #1629

Open

Description

[agent] Found by the scheduled Yarn classic (1.x) bug-hunt routine (ledger #304).

Summary

This is the yarn classic twin of #1111 (pnpm, fixed) and #1621 (Bun, PR #1622, which explicitly keeps yarn on npm). When socket-patch was installed with yarn 1, socket-patch --update refuses with managed_install, says the binary "is managed by npm", and suggests an npm command. For a yarn global add install, that command does nothing:

How it was installed Hint on main 657fce2 What following the hint does
yarn global add @socketsecurity/socket-patch (default global dir, e.g. ~/.config/yarn/global, /usr/local/share/.config/yarn/global as root) npm update -g @socketsecurity/socket-patch npm prints up to date, and the yarn copy stays on 4.0.0. yarn global upgrade @socketsecurity/socket-patch --latest moves it to 5.0.1.
yarn global add with a custom --global-folder / global-folder (dir not named global) npm install @socketsecurity/socket-patch@latest Classified as a project, because the global folder holds yarn's package.json. Run from the user's cwd, the hint installs socket-patch into whatever project they're in.
yarn add @socketsecurity/socket-patch in a project npm install @socketsecurity/socket-patch@latest npm 7+ does rewrite yarn.lock, and yarn install --frozen-lockfile still passes. But npm leaves a stray package-lock.json beside yarn.lock, so every later yarn run warns package-lock.json found … It is advised not to mix package managers.

The passive update notice uses the same hint (crates/socket-patch-cli/src/update_notifier.rs:243).

Impact

Every yarn-global user is told to upgrade with a command that's a silent no-op. They stay on the old CLI while believing they've upgraded. Yarn project users get a second npm-family lock beside yarn.lock, which socket-patch's own hosted and vendored modes then also see.

Repro (Linux, Node 22, real yarn; run as a scratch user or with a scratch HOME)

export SOCKET_NO_UPDATE_CHECK=1
M=/path/to/socket-patch/target/release/socket-patch     # main 657fce2

# Global
yarn global add @socketsecurity/socket-patch@4.0.0
GD=$(yarn global dir)
for f in $(find $GD -path '*linux-x64*' -name socket-patch -type f); do cp $M $f; done
$(yarn global bin)/socket-patch --update --yes
#   Error: … (…/yarn/global/node_modules/@socketsecurity/socket-patch-linux-x64-gnu/socket-patch) is managed by npm;
#   update it with `npm update -g @socketsecurity/socket-patch` instead, or pass --force …   (exit 1)
npm update -g @socketsecurity/socket-patch      # "up to date in 233ms"
grep '"version"' $GD/node_modules/@socketsecurity/socket-patch/package.json   # still "4.0.0"
yarn global upgrade @socketsecurity/socket-patch --latest                      # control: -> "5.0.1"

# Project
mkdir proj && cd proj
echo '{"name":"proj","version":"1.0.0","private":true,"dependencies":{"left-pad":"1.3.0"}}' > package.json
yarn add @socketsecurity/socket-patch@4.0.0
for f in $(find node_modules/@socketsecurity -path '*linux-x64*' -name socket-patch -type f); do cp $M $f; done
node_modules/.bin/socket-patch --update --yes   # … managed by npm; update it with `npm install @socketsecurity/socket-patch@latest` …
npm install @socketsecurity/socket-patch@latest # writes package-lock.json beside yarn.lock
yarn install --frozen-lockfile                  # passes, but: "warning package-lock.json found …"

The refusal happens before any network I/O.

Expected vs actual

CLI_CONTRACT.md:1100 says: "every other channel is refused with that channel's own upgrade command", and the managed-install row says the refusal "names the owning manager". Expected for a yarn 1 install: label yarn, and:

  • a yarn global store (the global dir from yarn global dir, which holds yarn's own package.json + yarn.lock): yarn global add @socketsecurity/socket-patch@latest. yarn global upgrade … --latest also works.
  • a project whose outermost node_modules holder has yarn.lock (and no berry .yarnrc.yml / __metadata): yarn add @socketsecurity/socket-patch@latest.

Actual: channel_label_for reports npm, and upgrade_hint_for returns npm commands. Row CLI_CONTRACT.md:1118 says "otherwise global (including a yarn global store …): npm update -g". That row contradicts line 1100, and it's the same catch-all #1111 / #1621 called the defect: npm update -g never looks in yarn's global dir.

OS × version

OS yarn Shape Hint Following the hint
Linux 1.22.22 global (default dir) npm update -g … no-op, stays 4.0.0 (×2)
Linux 1.10.1 global (default dir) npm update -g … no-op, stays 4.0.0
Linux 1.22.22 global, custom --global-folder npm install …@latest wrong target (not run)
Linux 1.22.22 project npm install …@latest stray package-lock.json, yarn warns; frozen install still passes
Linux any yarn global upgrade … --latest (control) n/a upgrades to 5.0.1

macOS and Windows weren't probed. The classification is path-based (%LOCALAPPDATA%\Yarn\Data\global\node_modules takes the same global branch), so they should behave the same way. Not a regression: the code says yarn has "no dedicated hint yet".

Suspect code

  • crates/socket-patch-core/src/update/channel.rs:198 (node_manager): "Anything else is npm, which also covers yarn and Bun (no dedicated hint yet)". There's no Yarn variant.
  • crates/socket-patch-core/src/update/channel.rs:144 (upgrade_hint_for) and :171 (channel_label_for).
  • crates/socket-patch-core/src/update/channel.rs:268 (is_global_npm_install): it treats a yarn global store as an npm global.
  • crates/socket-patch-cli/CLI_CONTRACT.md:1118.
  • PR Fix Bun installs getting npm self-update hints (#1621) #1622 (open, Bun) touches the same function and keeps a test asserting the yarn global store gets npm update -g, so the two will need reconciling.

Reported to the Yarn classic routine as a handover from the Bun routine (#1621). No probe runs (Linux only).

Activity

  1. mikolalysenko commented on Oct 17, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Triaged: priority:p1 (yarn classic / npm family). Confirmed on main 7d3086f: node_manager (crates/socket-patch-core/src/update/channel.rs) has no Yarn variant ("Anything else is npm, which also covers yarn and Bun"), so channel_label_for says npm and upgrade_hint_for gives npm update -g / npm install. This isn't a duplicate.

    Shares root cause with #1621: update::channel::node_manager only models npm, pnpm and vlt, so every other npm-family manager falls through to npm's label and hint. Will be fixed together. #1621 is being fixed in PR #1622, which is ready and green but keeps yarn on npm (it asserts that a yarn global store gets npm update -g). #1629 needs a follow-up on top of #1622, or #1622 can be widened if its owner takes it back.


    Generated by Claude Code

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