Repository navigation
vendor --check fails a vendored npm package that has a bundled duplicate with "wiring missing: no lockfile or config references …", although the lock does reference it, and its socket-patch vendor remedy is a no-op #1232
Description
[agent] Found by the scheduled npm bug-hunt routine (ledger #302).
Summary
A project installs ms@2.1.2 twice: once as a normal registry entry (node_modules/ms) and once bundled inside another package (node_modules/wrap/node_modules/ms, inBundle: true). scan --mode vendored vendors the registry entry, warns that the bundled copy can't be rewritten, and exits 0. That part is correct.
vendor --check then fails the entry (exit 1). Failing is reasonable, because the bundled copy really does install unpatched. The problem is the reason and the remedy it gives:
pkg:npm/ms@2.1.2: wiring missing: no lockfile or config references .socket/vendor/npm/<uuid> any more, so a fresh install gets the unpatched package; re-run `socket-patch vendor` to rewire it
- The reason is false.
package-lock.jsonnode_modules/msresolves tofile:.socket/vendor/npm/<uuid>/ms-2.1.2.tgz, andnpm ciinstalls the patched bytes there. - The remedy loops.
socket-patch vendorprints "No manifest to vendor from; 1 vendored entry is tracked in the ledger —socket-patch repairverifies it." and exits 0.repairprints "Repair complete." A re-run ofscan --mode vendoredsays "1 package is already vendored; nothing to do."vendor --checkis still red with the same text after all three.
This is the bundled-copy version of the hasShrinkwrap case that #1008 just fixed for #753 ("Fail vendor --check on a copy under a hasShrinkwrap dependency"). That commit called the same "wiring missing … re-run socket-patch vendor" text "wrong twice over" and gave the hasShrinkwrap case its own reason. Bundled copies still fall through to the generic message.
Impact
CI that gates on vendor --check goes red with advice that can't work. The real cause (a dependency bundles an unpatched copy, so that dependency has to be updated) isn't named anywhere in the check output. A user who follows the advice re-vendors, sees "nothing to do", and is stuck. Bundled duplicates are common in practice: npm itself bundles ansi-regex, semver and others.
Repro (Linux; a local mock of the org patch API serves one free patch for ms@2.1.2; every command gets --api-url <mock> --org o --api-token fake --patch-server-url <mock>)
mkdir -p wrap p
(cd wrap && echo '{"name":"wrap","version":"1.0.0","dependencies":{"ms":"2.1.2"},"bundleDependencies":["ms"]}' > package.json \
&& echo 'module.exports=require("ms")' > index.js && npm i && npm pack)
cd p && git init -q
echo '{"name":"p","version":"1.0.0","dependencies":{"ms":"2.1.2","wrap":"file:../wrap/wrap-1.0.0.tgz"}}' > package.json
npm i # lock: node_modules/ms (registry) + node_modules/wrap/node_modules/ms {inBundle: true}
socket-patch scan --mode vendored --yes # exit 0; warns the bundled copy stays unpatched
socket-patch vendor --check # exit 1, "wiring missing: no lockfile or config references …"
socket-patch vendor # exit 0, "No manifest to vendor from; … `socket-patch repair` verifies it."
socket-patch scan --mode vendored --yes # "1 package is already vendored; nothing to do."
socket-patch vendor --check # still exit 1, same textOutput (npm 10.9.4):
scan --mode vendored exit=0
lock node_modules/ms -> file:.socket/vendor/npm/8b4293f1-51e3-575f-98ec-a45193cf7433/ms-2.1.2.tgz
pkg:npm/ms@2.1.2: wiring missing: no lockfile or config references .socket/vendor/npm/8b4293f1-51e3-575f-98ec-a45193cf7433 any more, so a fresh install gets the unpatched package; re-run `socket-patch vendor` to rewire it
vendor --check exit=1
No manifest to vendor from; 1 vendored entry is tracked in the ledger — `socket-patch repair` verifies it.
vendor exit=0
1 package is already vendored; nothing to do.
vendor --check exit=1 (after both remedies)
The hosted → vendored takeover over the same project (now possible since the #828 fix) ends in the same state.
vex gets the reason right: patched_ref_unattributable: … also installs a bundled copy of it at "node_modules/wrap/node_modules/ms" …, followed by vendor_unwired.
Expected vs actual
- Expected (CLI_CONTRACT.md,
vendor --check): "The reason names the cause". The contract lists specific reasons for a contested lock, a removed dependency, an unwired same-lock copy (npm vendored vex and vendor --check pass while a second registry copy of the patched package@version in the same package-lock.json stays unwired and installs unpatched #588), a copy under ahasShrinkwrappackage (npm hosted and vendored modes rewrite a lock entry nested under a dependency that ships npm-shrinkwrap.json (hasShrinkwrap), so npm 7–11 install it unpatched while vendored VEX attests not_affected #753, "the reason names the entry and its shrinkwrapping dependency, which must be updated since re-vendoring cannot reach that copy") andallow-file(Vendored npm scan wires file: tarballs that npm ≥ 11.14 refuses under allow-file=root (transitive deps) or allow-file=none, so every npm ci fails EALLOWFILE while scan, vendor --check and vex report success with no warning #969). A bundled copy needs the same treatment: namenode_modules/wrap/node_modules/msand its bundling parent, and say to update that parent. - Actual: the generic "wiring missing" fallback, which is false here, and a remedy that is a no-op.
Matrix
| OS | npm (lockfileVersion) | Reproduces |
|---|---|---|
| Linux | 8.19.4 (v2) / Node 22 | yes |
| Linux | 10.9.4 (v3) / Node 22 | yes (×3, including via the hosted → vendored takeover) |
| Linux | 12.2.0 (v3) / Node 24 | yes |
| macOS / Windows | — | untested (probe branches paused). The logic is OS-independent. |
First bad: pre-existing. Main 16106b1 (before #1008) behaves the same. Tested on main f3c6313.
Suspect code
crates/socket-patch-core/src/vendor/npm_lock.rs:909(check_wiring): skips bundled / link / non-registry copies (scan_lock_matchespushes them intoskipped, and that list is then dropped). OnlyhasShrinkwrapcopies get their own failure (:940-964). So the wiring audit passes, and the liveness rule fails afterwards.crates/socket-patch-cli/src/commands/vendor.rs:505(unwired_check_failure): the fallback "wiring missing" message is reached because discovery dropped the ref aspatched_ref_unattributable(crates/socket-patch-core/src/vex/discover/npm.rs), not because no lock references the artifact.
Related: #753 (same shape for hasShrinkwrap, fixed in #1008), #828 (hosted unwind with a bundled copy, fixed), #325 (in-run VEX and bundled copies).
Activity
mikolalysenko commentedon Oct 9, 2026
[agent] Triage: priority:p1 (npm). Not a duplicate: the bundled-copy counterpart of the hasShrinkwrap case #1008 fixed for #753. No open PR covers it.
Generated by Claude Code
mikolalysenko commentedon Oct 9, 2026
[agent] Bun bug-hunt routine (ledger #306): Bun reproduces this too, on both the text
bun.lockand the binarybun.lockb. I'm adding it here rather than filing a duplicate, since the reason and the remedy loop are the same.Shape:
{"dependencies":{"left-pad":"1.3.0","bparent":"file:./bparent-1.0.0.tgz"}}, wherebparentbundlesleft-pad@1.3.0(bundledDependencies). Bun's text lock records"left-pad"plus"bparent/left-pad": [..., { "bundled": true }, ...], andbun.lockbkeeps one record marked as also bundled.scan --mode vendoredexits 0 and a fresh-checkoutbun install --frozen-lockfileinstalls the patchednode_modules/left-pad(the bundled copy stays unpatched, as expected). Then:vendor --check→ exit 1,vendor_check_failed: "wiring missing: no lockfile or config references .socket/vendor/npm/<uuid> any more, so a fresh install gets the unpatched package". The lock does reference it.socket-patch vendor→noManifest, exit 0.listshows the entry.vendor --checkstays red.Linux, main
60300b8, reproduced twice. The fix for this issue should covervendor/bun_lock.rsandvendor/bun_binary.rsas well as the npm lock.Generated by Claude Code
mikolalysenko commentedon Oct 9, 2026
v5 triage: P2, not a release blocker. Drop P1 to P2: the checker correctly refuses the unpatched bundled copy; the remaining defect is its reason/remedy text.
This follows the maintainer's release scope: one normally completing CLI instance, prioritizing valid-lockfile patch/install behavior, compatibility, and actionable CLI UX.
mikolalysenko commentedon Oct 14, 2026
[agent] Re-triage by the npm bug-hunt routine (ledger #302): fixed on main
37c8918. The fix arrived through 81dd140 (#1513, "Fix vendored npm VEX beside a file: dir copy"), which added thecopy unpatchedreason tovendor --check(crates/socket-patch-cli/src/commands/vendor.rs:480).I reran the issue's repro on npm 10.9.4 / Node 22:
ms@2.1.2at the root, plus a copy bundled insidewrapfromfile:../wrap/wrap-1.0.0.tgz.scan --mode vendored --yesexits 0, thenvendor --check:The reason now names the bundled copy, and the remedy no longer sends you back to
socket-patch vendor. Run 40 still reproduced the old text on887a5f7, so this is the change. Closing.Generated by Claude Code