Repository navigation
Conversation
The stored hash was a field on Lockfile that each producer had to fill before a save. The pnpm migrator never did, so a bun.lockb written from pnpm-lock.yaml stored zeros and the next frozen install failed. The yarn and npm migrators filled it before the lifecycle scripts were known, so bun pm migrate to bun.lockb failed the same check when package.json had a root lifecycle script. generate_meta_hash now takes the script lines from the package columns, and the writer computes the hash from the packages it writes unless the comparison before the save already did. The hash a bun.lockb was loaded with is kept only to compare. bun pm migrate and bun pm trust save a migration as bun.lockb through one entry that first takes lifecycle scripts from package.json and drops unreferenced packages, as the next install does.
… saves and a lockfile without one
Collaborator
Author
|
Updated 10:21 PM PT - Oct 2nd, 2026
✅ @robobun, your commit 56ce66a5857e105b73bdadf4cb367510b70540d3 passed in 🧪 To try this PR locally: bunx bun-pr 44501That installs a local version of the PR into your bun-44501 --bun |
Collaborator
Author
|
Status: draft. The self-review of this diff is in progress. How I reproduced it (1.4.3-canary.1 at 367d939, and a debug build of main):
The same steps from PR: #44501 |
This was referenced Oct 7, 2026
Draft
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
bun ciexits 1 witherror: lockfile had changes, but lockfile is frozen.Lockfile.meta_hash(src/install/lockfile/bun.lockb.rs:186). The pnpm migrator never fills that field. The yarn and npm migrators fill it without lifecycle scripts, so a rootpostinstallfails the same check.Fix
generate_meta_hashtakes the script lines from the package columns. The writer hashes the packages it writes, unless the comparison before the save did.Lockfile.meta_hashbecomesloaded_meta_hash: Option<MetaHash>, which code only compares. Without a stored hash, the frozen check usesLockfile::eql.bun pm migrateandbun pm trustsave through one entry. It prepares a migrated lockfile like the next install does.test/cli/install/bun-lockb.test.tsandtest/cli/install/migration/, 20 fail on 1.4.3-canary.1. Notes list the other suites.Background
name@resolutionlines and the lifecycle scripts of the root and workspaces. A frozen install compares the stored hash with a fresh one.Lockfile::eql.bun add.Downsides
bun pm migrateto bun.lockb does more work. Its save step takes 1.6M instructions and 52 allocations at 202 packages (base 0.15M, 18).bun pm hash-printprints zeros in a project with only yarn.lock or package-lock.json.save_to_disktakes 871,346 instructions at 1,002 packages (base 871,273).Notes
Measurements. Release builds of the merge base and of this branch, linux-x64. Counts come from gdb breakpoints and a ptrace single-step counter.
strace,perf,valgrindandbloatyare not in the container, so syscall counts use gdb catchpoints and sizes usesize.--lockfile-only1/0, bun.lock frozen 0/0, bun.lock add 0/0, bun.lockb no-op 1/1, bun.lockb fresh 1/1, bun.lockb frozen 1/1, bun.lockb add 1/1, bun.lockb remove 1/1, bun.lockb--lockfile-only1/1, pnpm to bun.lockb install 0/1, pnpm to bun.lock install 0/0, npm to bun.lock install 2/2, npm to bun.lockb install 2/2, yarn to bun.lock install 2/2,bun pm lson a yarn.lock project 1/0,bun pm lson a pnpm project 0/0,bun pm migratepnpm to bun.lockb 0/1, pnpm to bun.lock 0/0, npm to bun.lockb 1/1, yarn to bun.lockb 1/1, npm to bun.lock 1/0,bun install --yarnon bun.lock 0/1.bun addat 1,002 packages: 871,346 instructions, 18 allocations (base 871,273, 18). At 202 packages: 141,008 and 18 (base 141,010 to 141,700 and 18).install_with_manager(base 5,939,051). Fresh--lockfile-onlyinstall to bun.lock: 5,389,872 (base 5,879,068).bun pm migrateto bun.lockb: 1 (base 0). Perbun pm migrateto bun.lock: 0 (base 0).bun pm migrateto bun.lockb: clean_with_logger calls 1 (base 0). Save step at 202 packages: pnpm 1,600,203 instructions and 52 allocations, npm 1,845,084 and 489 (base 146,858 and 18, 146,488 and 18).bun pm migrateto bun.lock: 1,893,448 instructions (base 1,893,390), same allocations.bun cion the PR build. Bytes differing after a re-save by the PR build: 0.bun pm trustkeeps the stored hash.test/cli/install/migration, 275 rows: unchanged flips 0 of 97, dependency-deleted flips 0 of 81, root-hook rows 1 to 0: 52 (48 package-lock.json, 4 yarn.lock), 0 rows go 0 to 1.pm migrate,install,install --lockfile-only,addandremove, times seven project shapes (plain, root postinstall, root binding.gyp, root prepare plus binding.gyp, an unreferenced lock entry, a workspace postinstall, a workspace binding.gyp).bun pm migrateto bun.lockb againstbun install --lockfile-onlyon the same input, 14 cases: 14 store the same meta hash (base 3), 4 files are byte-identical (base 0). The others differ by one byte (configVersion, which install: lockfile parity forbun pm migrate,bun pm trustand yarn.lock entries without#sha1#41908 changes) or two (a pnpm importer literal, which install: migrate pnpm importer rows in the shape package.json parsing produces #38791 changes).size).--verboseper flow (base/PR): fresh bun.lock 1/1, bun.lock no-op 0/0, fresh text--lockfile-only1/1, bun.lockb no-op 1/1, bun.lockb frozen 1/1, bun.lockb--lockfile-only1/1, fresh bun.lockb 1/1, pnpm to bun.lockb 0/0, npm to bun.lock 1/1. The blocks are identical.Behaviour that changes.
Lockfile::eql, the check bun.lock uses, and a plain install writes the hash. Before, the frozen install failed until a plain install ran. Files from the pnpm migration of 1.2.23 to 1.4.2 are in this state.bun install --yarnprints the hash of the lockfile in the yarn.lock header when it loaded a bun.lock. Before, it printed zeros.bun bun.lockbdoes the same for a file without a stored hash.bun pm hashandbun pm hash-stringare unchanged. They hash packages only.bun pm migrateandbun pm trustno longer abort a debug build when a migrated pnpm-lock.yaml has patchedDependencies and the output is bun.lockb. Two debug assertions required a patch file hash that only an install computes. They are gone. install: lockfile parity forbun pm migrate,bun pm trustand yarn.lock entries without#sha1#41908 removes the same one in the writer.Differences from the design review.
Not covered.
bun pm migrateto bun.lockb from a yarn v1 workspace project with a workspace lifecycle script. The yarn migrator creates no workspace rows, so the direct save has nothing to fill. This is from reading the code. I did not measure it.Overlap with open PRs. #43912 adds
Scripts::wants_default_node_gyp. This branch adds the same helper with the same text, so the two merge with one trivial conflict inload_root_lifecycle_scripts. #44294 conflicts in one line ofpackage_manager_command.rs. #41908 touchessave_to_disk,bun pm migrateandbun pm trust. #40057 adds a migrator that assignsmeta_hash. That line goes away with the field.Suites run with the debug build.
bun-lockb,bun-pm,bun-lock,bun-workspaces,bun-install,bun-install-registry,bun-install-lifecycle-scripts,frozen-lockfile-pruned,frozen-lockfile-missing-workspace,migrate-bun-lockb-v2,lockfile-version-2,lockfile-only,overrides,config-version,bun-update-lockfile-syncand all oftest/cli/install/migration/. Failures that also occur without this change: the bitbucket, gitlab and external tarball tests inbun-install.test.tsneed the network.ensureTempNodeGypScript worksandnode -p should work in postinstall scriptsclear PATH and need a binary namedbun.manifest conditional requests > a changed etag returns 200fails about one run in three on the debug build. Several files need more than the 5 s default per test on a debug build.