Repository navigation
pnpm-workspace.yaml with a UTF-8 BOM: hosted and vendored miss the first top-level key and append a duplicate trustLockfile / overrides, so every pnpm install fails with "duplicate mapping key" after a successful scan #904
Description
[agent] Found by the scheduled pnpm bug-hunt routine (ledger #303).
Summary
formats::pnpm::workspace::top_level_key (the scanner #402 introduced so the workspace-file splices see every key spelling) doesn't strip a leading UTF-8 BOM. When pnpm-workspace.yaml starts with \xEF\xBB\xBF and its first top-level key is the one socket-patch edits, the key reads as \u{FEFF}trustLockfile (or \u{FEFF}overrides) and isn't recognised. pnpm's YAML parser strips the BOM and sees the real key, so it accepts the file as it stands.
- Hosted (
scan --mode hosted, 9.0 lock): the existingtrustLockfile:is missed, and a secondtrustLockfile: trueis appended. If the user wrotetrustLockfile: false, that explicit choice is no longer respected, though CLI_CONTRACT says explicit user settings are preserved. Either way the file now has a duplicate key. - Vendored (
scan --mode vendored, pnpm 10+ workspaceoverrides:mirror): the existingoverrides:block is missed, and a second top-leveloverrides:with thefile:.socket/vendor/…entry is appended.
Both runs report status: success, exit 0.
Impact
pnpm then refuses to parse the workspace file, so every pnpm command in the project fails, not just installs of the patched package:
- pnpm 12.8.1:
pnpm-workspace.yaml: error: line 4 column 1: duplicate mapping key: trustLockfile, set DuplicateKeyPolicy in Options if acceptable - pnpm 11.28.3:
[ERROR] duplicated mapping key (4:1)
This is the failure class #402 fixed for quoted and key : spellings, reached through a BOM, for example from a Windows editor that saves "UTF-8 with signature". Unlike the vendored lock/package.json gates (vendor_lockfile_crlf_unsupported, vendor_pkg_json_unsupported for a BOM), nothing refuses the file.
Repro (Linux, main 9c43dfc, local mock of the patch API)
# hosted
mkdir h && cd h
echo '{"name":"b","version":"1.0.0","dependencies":{"left-pad":"1.3.0"}}' > package.json
printf '\xef\xbb\xbftrustLockfile: false\npackages:\n - .\n' > pnpm-workspace.yaml
pnpm install # OK (pnpm 12.8.1)
socket-patch scan --mode hosted --yes --json # status success, rewrittenFiles: [pnpm-lock.yaml, pnpm-workspace.yaml]
grep -c trustLockfile pnpm-workspace.yaml # 2
rm -rf node_modules && pnpm install --frozen-lockfile # duplicate mapping key: trustLockfile
# vendored
mkdir ../v && cd ../v
echo '{"name":"b","version":"1.0.0","dependencies":{"left-pad":"1.3.0"}}' > package.json
printf '\xef\xbb\xbfoverrides:\n is-number: 7.0.0\npackages:\n - .\n' > pnpm-workspace.yaml
pnpm install
socket-patch scan --mode vendored --yes --json # status success
grep -c 'overrides:' pnpm-workspace.yaml # 2
rm -rf node_modules && pnpm install --frozen-lockfile --offline # duplicate mapping key: overridesExpected vs actual
- Expected: CLI_CONTRACT's pnpm trust-config paragraph says the write "preserves explicit user settings (an existing top-level key in any YAML spelling …)", and that "a file a line append would corrupt … is left untouched and the warning gives the manual recoveries". The vendored
overrides:mirror "reads keys the same way". So either the BOM is stripped before the keys are matched (a BOM'dtrustLockfile: trueis then already configured, andfalseis respected), or the file is left untouched with the manual-recovery warning. - Actual: a duplicate key is appended, the scan reports success, and pnpm can't parse the file.
Matrix (Linux; each cell run at least twice in fresh projects)
| arm | first key | pnpm | main 9c43dfc |
release 4.0.0 |
|---|---|---|---|---|
| hosted | trustLockfile: true |
12.8.1 | fail (duplicate) | fail |
| hosted | trustLockfile: false |
12.8.1 | fail (duplicate; explicit false overridden) |
not run |
| hosted | trustLockfile: true |
11.28.3 | fail | not run |
| vendored | overrides: |
12.8.1 | fail (duplicate) | fail |
| hosted | BOM + packages: first (control) |
12.8.1 | pass (key appended once, install patched) | — |
Not a regression. The code path is OS-independent; no macOS/Windows probe.
Suspect code
crates/socket-patch-core/src/formats/pnpm/workspace.rs:20(top_level_key): checksline.as_bytes().first()and splits on:without stripping\u{FEFF}from the first line.block_section_bounds(:111) inherits it.- Callers:
crates/socket-patch-core/src/hosted/guidance.rs:265(trust plan),crates/socket-patch-core/src/vendor/pnpm_lock.rs:1792/:1827(overrides mirror), and the readers inpatch/redirect/upstream/npm.rs:436/:1047andcrawlers/npm_crawler.rs:113. - Related: Hosted pnpm scan skips the
trustLockfile: trueauto-config when pnpm-lock.yaml starts with a UTF-8 BOM, so pnpm 11/12 frozen installs fail with ERR_PNPM_TARBALL_URL_MISMATCH after a successful scan #903 (the BOM-blindlockfileVersionsniff forpnpm-lock.yaml) and pnpm-workspace.yaml edits miss quoted or space-before-colon top-level keys, append a duplicatetrustLockfile/overrideskey, and break every install #402 (the same duplicate-key failure for other spellings).
Probe runs: none (Linux reproduction only).
Activity
mikolalysenko commentedon Oct 6, 2026
[agent] Structural cause tracked in #905.
workspace::top_level_keydoesn't skip a BOM, while the otherpnpm-workspace.yamlkey reader (governing_root::workspace_lockfile_dir) does. This is one of about 50 hand-rolled BOM decisions. #905 adds one sharedstrip_bomand makesworkspace_lockfile_diratop_level_keycaller.Generated by Claude Code
mikolalysenko commentedon Oct 6, 2026
[agent] Shares root cause with #903, #905: the
formats::pnpmlock and workspace readers (head_lock_version,lock_versions,is_pnpm_lock_text,workspace::top_level_key) match a column-0 literal and never skip a leading UTF-8 BOM. Will be fixed together.Generated by Claude Code
mikolalysenko commentedon Oct 6, 2026
[agent] Claiming this issue (with #903, #905; shared root cause: pnpm lock/workspace readers don't skip a leading UTF-8 BOM). Branch: agent/fix-pnpm-bom-readers. Claim-ID: 2026-10-06T01:20:29Z-3fcf3e
Generated by Claude Code
mikolalysenko commentedon Oct 6, 2026
[agent] Fix in progress: #909
Generated by Claude Code
Read BOM-prefixed pnpm locks and workspace files
Test hosted pnpm scan/rollback on BOM files
mikolalysenko commentedon Oct 6, 2026
[agent] Version data from pnpm bug-hunt run 25 (main
9c43dfc, Linux): vendored mode reproduces on pnpm 9.15.9 and 10.34.5 as well as 11 / 12. The repro is a BOMpnpm-workspace.yamlwhose first key isoverrides:(is-number: 7.0.0).scan --mode vendoredexits 0 withsuccessand appends a second top-leveloverrides:block forleft-pad@1.3.0. The nextpnpm install --frozen-lockfilefails on the duplicate key at line 6, so nothing is installed.Control: with the same BOM file but
packages:as the first key (sooverrides:is new), both versions pass and install the patched bytes. #909's tests may want a pnpm ≤10 vendored leg.Generated by Claude Code
Fix pnpm lock/workspace readers missing a BOM (#903, #904, #905) (#909)
pnpm bug-hunt run 30: file #1074, re-verify #935/#956/#903/#904