bun install --frozen-lockfile: Deterministic CI Installs
bun install --frozen-lockfile installs strictly from bun.lock and fails if package.json and the lockfile disagree.
Frozen installs are the foundation of reproducible CI: the runner installs exactly what was committed, and a drifted lockfile fails the build instead of resolving fresh versions behind your back.
What it does
With --frozen-lockfile, bun install never modifies bun.lock. If the lockfile is missing, out of date, or inconsistent with package.json, it errors instead of re-resolving. Bun also enables frozen behavior automatically when it detects a CI environment (CI=true), so the flag is often implied.
Common usage
bun install --frozen-lockfile
# Bun treats CI=true as implying frozen; the flag is explicit insurance
CI=true bun install --frozen-lockfileOptions
| Flag / env | What it does |
|---|---|
| --frozen-lockfile | Fail rather than change the lockfile |
| CI=true | Bun auto-enables frozen-lockfile behavior |
| --no-frozen-lockfile | Force a non-frozen install even in CI |
| --production | Combine with frozen to install prod deps only |
In CI
Make --frozen-lockfile explicit in your install step so the intent is clear and not dependent on CI detection. The contract is: developers run bun install locally, commit the updated bun.lock, and CI installs from it unchanged. Pair with oven-sh/setup-bun and a cache of ~/.bun/install/cache keyed on the lockfile.
Common errors in CI
"error: lockfile had changes, but lockfile is frozen" is the headline failure: package.json changed without an updated bun.lock. Fix it by running bun install locally and committing bun.lock. The same error appears when someone edits a version in package.json by hand. If the lockfile is simply missing, the message is that no lockfile was found.