Engineering · 3 min read

The fault that was already there

A version pin that had worked for months broke immediately in a new repository. Nothing had changed in the old one. That is the interesting part.

We started a new repository and copied the Docker base image and CI configuration from an existing one. Both pinned Bun to 1.3.14. The existing project had been building on that pin for months.

The new repository failed on its first CI run:

``` error: Unknown lockfile version at bun.lock:2:22 UnknownLockfileVersion: failed to parse lockfile ```

Bun 1.3.14 cannot read lockfile version 2. Current Bun releases write version 2. The old repository's lockfile was still version 1, generated back when its pin was current, so it kept working. The new one was generated with a current Bun, so it did not.

Nothing had changed in the old repository. It was already broken. It just had not been asked the question yet.

Where latent faults surface

The old project would have failed the next time anyone ran `bun install` and committed the result. Adding a dependency. Bumping a package. Any routine change.

And the failure would have arrived attached to that change. The author would see CI fail on a pull request that adds a logging library, and reasonably conclude the logging library broke the build. They would spend an hour on the wrong thing before reading the error properly.

This is what makes latent faults expensive. Not the fix — the fix was three lines. The cost is that they surface at a moment chosen by chance, attached to an innocent change, in front of someone who has no reason to suspect a version pin they have never looked at.

Why the new repository found it

A new project has no history to protect it. Every generated artefact is generated now, with current tools, so every assumption made at pin time is tested immediately.

That is a genuinely useful property and worth using deliberately. Standing up a new service from an existing template is a free audit of the template. Everything that has been quietly true-by-accident in the old project becomes a hard failure in the new one, on day one, with nothing else in flight to confuse it.

We fixed the new repository, then opened a pull request against the old one. Both now pin 1.4.1.

Verifying the fix in the direction that matters

The obvious check is that the new lockfile works with the new pin. The check that actually mattered was the opposite one: does the **new** Bun still read the **old** lockfile without rewriting it?

If it did not, bumping the pin would have forced a lockfile regeneration in a live product repository — a much larger change, with a much larger diff, and a real risk of dependency drift smuggled in alongside a version bump.

It does. `bun install --frozen-lockfile` under 1.4.1 left the version 1 lockfile byte-identical, confirmed against `git status`. So the pin change is genuinely a pin change: three lines, no lockfile churn, no dependency movement. Lint, type checks and 477 unit tests passed unchanged.

The general shape

A pinned version is a claim about compatibility that was true when you wrote it. Nothing re-checks it. The pin does not age; the world around it does.

Two habits follow. When you copy infrastructure between projects, treat the copy as a test of the original rather than as a shortcut. And when you bump a pin, check compatibility in the direction that lets you make the smallest change, not the direction that is easiest to test.