Skip to content

Hosted pin on a bun.lockb record that Bun shares with a bundled copy can't be unwound: list errors, and the vendored takeover fails (#1008's #828 fix covers the text bun.lock only) #1243

Description

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

Summary

A Bun project installs left-pad@1.3.0 twice: once as a direct registry dependency, and once bundled inside another package (bundledDependencies). Bun's binary bun.lockb (1.2.x and later) keeps one package record for left-pad@1.3.0 and marks it as also bundled. A hosted scan wires that record, because the redirect writer handles shared records on purpose: "one Bun shares with a regular install is still redirected for that install". It warns redirect_bun_bundled_instance_skipped ("is also bundled…") and exits 0. The fresh install is correct: the direct copy is patched and the bundled copy is not.

After that, socket-patch can't manage the pin it just wrote. This is the #828 failure, which #1008 fixed for npm and for Bun's text bun.lock, but not for bun.lockb:

  1. list exits 1 with hosted_wiring_contested ("bun.lockb: package Remove tsc from npm prepare script #1: pkg:npm/left-pad@1.3.0 is wired to a Socket patch, but bun installs this entry as a bundled dependency…"). Its remedy, "re-run socket-patch scan --mode hosted", writes the same state again.
  2. The hosted → vendored takeover (scan --mode vendored) exits 1, partial_failure, vendor_lock_entry_not_found: "bun.lockb has no registry entry for left-pad@1.3.0". The hosted pin is never recognized, so it's never restored before vendoring.
  3. remove and rollback refuse it on the same hosted_wiring_contested path. A hosted bun.lockb rollback is documented to refuse with the git checkout -- bun.lockb remedy, but here the reason given is contested wiring.

The same project with a text bun.lock passes on the current main: list succeeds, the takeover vendors, and vendor --revert restores the pre-hosted lock byte for byte. That shows the #828 fix works for text locks.

Impact

A user with a bundled duplicate (Bun's lockb merges it with the regular install) who tries hosted mode can't list the pin or move to vendored mode, and the remedy it prints loops. The only way out is git checkout -- bun.lockb. VEX is not affected: discovery withholds the attestation, which is correct while the bundled copy stays unpatched.

Repro (Linux, Bun 1.4.2; patch API mocked locally)

# a parent package that bundles left-pad@1.3.0
mkdir -p bparent/package/node_modules/left-pad && cd bparent/package
echo '{"name":"bparent","version":"1.0.0","dependencies":{"left-pad":"1.3.0"},"bundledDependencies":["left-pad"]}' > package.json
echo 'module.exports=require("left-pad")' > index.js
curl -sL https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz | tar xz --strip-components=1 -C node_modules/left-pad
cd .. && tar czf bparent-1.0.0.tgz package && cd ..

mkdir proj && cd proj && cp ../bparent/bparent-1.0.0.tgz .
echo '{"name":"bt","version":"1.0.0","dependencies":{"left-pad":"1.3.0","bparent":"file:./bparent-1.0.0.tgz"}}' > package.json
printf '[install]\nsaveTextLockfile = false\n' > bunfig.toml
bun install                                   # writes bun.lockb: one left-pad@1.3.0 record, also bundled
git init -q && echo node_modules/ > .gitignore && git add -A && git commit -qm init

socket-patch scan --mode hosted --json        # exit 0, redirected 1, redirect_bun_bundled_instance_skipped ("also bundled")
git add -A && git commit -qm hosted
socket-patch list --json                      # exit 1, hosted_wiring_contested (patched_ref_unattributable … bundled dependency)
socket-patch scan --mode vendored --json      # exit 1, partial_failure, vendor_lock_entry_not_found

With bunfig.toml removed (text bun.lock, which has separate "left-pad" and "bparent/left-pad" entries with { "bundled": true }), list exits 0 and the takeover and vendor --revert succeed.

Expected vs actual

Matrix (Linux; current main 60300b8; reproduced twice on 1.4.2)

Bun lock hosted scan list hosted → vendored takeover
1.1.39 bun.lockb exit 0, no bundled flag recorded pass pass
1.2.23 bun.lockb exit 0, "also bundled" exit 1 contested exit 1 vendor_lock_entry_not_found
1.3.9 bun.lockb exit 0, "also bundled" exit 1 exit 1
1.4.2 bun.lockb exit 0, "also bundled" exit 1 exit 1
1.2.23 / 1.3.9 / 1.4.2 text bun.lock exit 0 pass pass (revert byte-exact)

macOS and Windows: untested (the format is the same; no probe run).

First bad

This isn't a regression. Before #1008 (793edd4), both the text lock and bun.lockb failed this way. #1008 (f3c6313) fixed the text lock only.

Suspect code

  • crates/socket-patch-core/src/vex/discover/bun.rs:287: if p.bundled { bundled.record(…) } routes any record a bundled edge reaches, including one Bun shares with a regular install (bundled_only == false), into Bundled::record.
  • crates/socket-patch-core/src/vex/discover/bun.rs:186-201: Bundled::record turns that record's ref into a DIAG_REF_UNATTRIBUTABLE diagnostic and drops it, rather than out.shadow(r) (which Bundled::contest, line 242, does for the text lock's separate regular entry).
  • crates/socket-patch-core/src/patch/redirect/bun_binary.rs:77-92: the writer deliberately wires shared records (if p.bundled_only { continue; }), so the reader and the writer disagree about them.

Related: #828 (npm, closed by #1008), #469 (bundled copies in vendored mode).

Activity

  1. mikolalysenko commented on Oct 9, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Triage: priority:p1 (Bun, npm family). Confirmed on main: vex/discover/bun.rs sends every record a bundled edge reaches into Bundled::record, including a bun.lockb record Bun shares with a regular install (bundled_only == false). That turns its ref into DIAG_REF_UNATTRIBUTABLE and drops it, where the text-lock path shadows it. Meanwhile redirect/bun_binary.rs deliberately wires shared records. No open PR covers this; #1009 and #1161 cover other Bun issues.


    Generated by Claude Code

  2. mikolalysenko commented on Oct 9, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Claiming this issue (shared root cause: bun.lockb discovery drops the ref of a record Bun shares between a regular and a bundled install instead of shadowing it). Branch: agent/fix-bun-lockb-shared-bundled-shadow. Claim-ID: 2026-10-09T08:21:15Z-9b5ab2


    Generated by Claude Code

  3. mikolalysenko commented on Oct 9, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Draft PR: #1247


    Generated by Claude Code

  4. added 3 commits that reference this issue on Oct 9, 2026
    537e25c
    bace573
    71410b6
  5. mikolalysenko commented on Oct 9, 2026

    @mikolalysenko
    CollaboratorAuthor

    v5 triage: P2, not a release blocker. Retain legacy binary Bun shared/bundled-record management at P2. The current text-lockfile workflow takes precedence; PR #1247 is pending.

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions