Repository navigation
Yarn berry vendored and hosted pins of native-addon packages (nan, bufferutil, utf-8-validate, node-addon-api) keep the registry entry's implicit node-gyp: "npm:latest" dependency, so vendored installs and hardened hosted installs fail YN0028 #737
Description
Activity
- addedbugSomething isn't workingSomething isn't workingbughuntFound by a scheduled package-manager bug-hunt agentFound by a scheduled package-manager bug-hunt agentpm:yarn-berryYarn Berry (2+)Yarn Berry (2+)
on Oct 4, 2026 mikolalysenko commented
on Oct 4, 2026 CollaboratorAuthorMore actions[agent] Triaged:
priority:p1(yarn berry). Not a duplicate of #718 (different field, and #719's head still fails per the table above).Shares root cause with #718: both Berry pin writers (
patch/redirect/mod.rs:3788"carries over verbatim",vendor/yarn_berry_lock.rscarried_sections) copy the registry entry body instead of rendering the entry yarn writes for the new locator. Will be fixed together. The in-flight fix for #718 is #719; this issue should join that PR's scope (derivedependencies/peerDependencies/dependenciesMetafrom the served tarball's manifest) rather than get a second, conflicting rewrite of the same writers.
Generated by Claude Code
mikolalysenko commented
on Oct 5, 2026 CollaboratorAuthorMore actions[agent] Yarn Berry bug-hunt re-triage (ledger #305): this still reproduces on main
4646693, which includes the merged #719. Tested with yarn 4.18.1 andnan@2.22.0, Linux, node-modules linker.- vendored: the pinned
file:entry still carriesdependencies: node-gyp: "npm:latest". A fresh-cloneyarn install --immutablefails YN0028. - hosted: a plain fresh
--immutableinstall passes. WithYARN_ENABLE_HARDENED_MODE=1it fails YN0028.
The new
formats/yarn/berry_entry.rs::render_pinned_entryonly replacesresolution,checksumandbinwith tarball-derived values.dependenciesstill carries over from the registry body, which is where yarn's implicitnode-gypdependency comes from.
Generated by Claude Code
- vendored: the pinned
- addedv5-blockerMust resolve before v5: public interface/migration or ordinary patch-install-undo failure.Must resolve before v5: public interface/migration or ordinary patch-install-undo failure.compatibilityPublic CLI/JSON, saved state, upgrades, or package-manager compatibility.Public CLI/JSON, saved state, upgrades, or package-manager compatibility.
on Oct 9, 2026 mikolalysenko commented
on Oct 9, 2026 CollaboratorAuthorMore actionsv5 release blocker (P1). Normal Yarn Berry native-addon dependencies retain registry-only node-gyp metadata and break immutable installs after patching.
This follows the maintainer's release scope: one normally completing CLI instance, prioritizing valid-lockfile patch/install behavior, compatibility, and actionable CLI UX.
mikolalysenko commented
on Oct 9, 2026 CollaboratorAuthorMore actions[agent] Claiming for v5 blocker burn-down (shared root cause: berry pin writers copy the registry entry's implicit node-gyp dependency). Branch: agent/v5-berry-node-gyp. Claim-ID: 2026-10-09T16:42:11Z-874e52
- added 2 commits that reference this issue
on Oct 9, 2026 - added a commit that references this issue
on Oct 9, 2026
[agent] Found by the scheduled Yarn Berry (2+) bug-hunt routine (ledger #305).
Summary
When yarn resolves a package through the npm registry and the registry metadata marks it as a gyp package, yarn adds an implicit
node-gyp: "npm:latest"dependency to the lock entry. When yarn resolves the same package through a tarball URL or afile:locator, it reads the manifest from the tarball and adds no such dependency.Both Berry pin writers build the pinned entry by copying the registry entry's body, so the implicit
dependencies: node-gyp: "npm:latest"is copied too:crates/socket-patch-core/src/patch/redirect/mod.rs:3788("dependencies, bin, languageName — carries over verbatim")crates/socket-patch-core/src/vendor/yarn_berry_lock.rs:336andcarried_sectionsat:1303On the next resolution, yarn drops that dependency together with the whole
node-gypsubtree (node-gyp, tar, undici, which, nopt and others; about 20 entries), so the lock no longer matches.This has the same root cause as #718 (copying the registry body instead of rendering the entry yarn writes for the new locator), but it affects a different field. #719 doesn't fix it: I built #719's head
635ca29and it still fails (see the table below). Once #719 lands and closes #718, this case stays broken, so I'm filing it separately.Impact
The affected packages are very common: every package whose published tarball ships a
binding.gypwith no install script. A survey with yarn 4.12.0 (comparing thenpm:entry with the tarball-URL entry) found the extra dependency on nan, node-addon-api, bufferutil, utf-8-validate (both are optional deps ofws), microtime, iconv and ref-napi. bindings and deasync are not affected.yarn install --immutablefails YN0028, and so does every CI run.--immutableinstall passes, but hardened mode (enableHardenedMode, which yarn turns on automatically for public PRs in GitHub Actions) or--refresh-lockfilefails YN0028.Repro (yarn 4.12.0, node-modules linker)
The patch API is a local mock that serves a patched tarball with its real
yarnBerry10c0checksum, which is bootstrapped with a real yarnresolutions: file:install. That's the same harness as #718.The pinned entry socket-patch writes (hosted):
A hardened install (with immutable off) rewrites it without the
dependencies:block and deletesnode-gyp@npm:latest,tar@npm:^7.5.7,undici@npm:^8.4.1and the rest of that subtree.Expected vs actual
yarn install --immutableaccepts (CLI_CONTRACT: the rewritten lock must install under frozen/immutable installs).Cells (Linux, Node 22, main
045d7ec)--immutable--immutable635ca29::__archiveUrlpin)Each failing cell reproduced at least twice. Hosted rollback of the nan pin restores both files byte-exactly, so it isn't affected.
First bad: hosted, #465 (
203e092), because release 4.0.0'snpm:locator pin kept yarn's registry resolution. I couldn't drive release 4.0.0's vendored flow against the mock.Suggested direction: derive
dependencies/peerDependencies/dependenciesMeta(not onlybin) from the served tarball'spackage.json, the way yarn's tarball/file fetchers do, rather than carrying the registry entry's maps over. Probe branches for macOS and Windows weren't possible this run (branch deletes are blocked in the routine's sandbox).