Skip to content

Migration numbering collides across parallel branches: two migrations numbered 26, one silently never applies #465

Description

@granludo

What happened

Two branches independently claimed migration number 26:

The runner applies only migrations above the recorded schema version. So whichever branch touches a database first records version 26, and the other branch's migration 26 is skipped forever on that database. Its tables never appear, and nothing reports an error — the schema version claims to be current.

This is not hypothetical. On the shared dev database the api_keys migration ran on 2026-07-08 at 16:09. LAMB_api_keys exists, LAMB_knowledge_stores does not, and the schema version reads 26. Every attempt to create a Knowledge Store failed against a table that was never created — reported, unhelpfully, as a name collision (filed separately).

migrations.py merges cleanly between the two branches, because they add functions at different line ranges. Git cannot see that two functions with the same number are a conflict, so neither review nor CI catches it.

Immediate fix

Applied on integration/456-merge: api_keys keeps 26 (it is already applied in the wild) and Knowledge Stores moves to 27, which applies cleanly on a database that has seen either branch. Version 26 is left as a documented gap.

The real problem

Sequential integers do not survive parallel branches. The next two people to add a migration in the same week will hit this again, and the failure is silent — a missing table, no error, and an error message pointing somewhere else entirely.

Worth considering:

  1. Non-sequential identifiers — timestamp or ULID-based migration ids with a recorded set of applied ids rather than a high-water mark. This is what makes the problem structurally impossible rather than merely unlikely.
  2. A CI guard — fail the build when two migration functions share a number, or when LATEST_VERSION does not match the highest defined migration. Cheap, catches the collision at PR time.
  3. A startup assertion — after migrations run, verify the tables each migration claims to create actually exist, and log loudly if not. This would have surfaced the problem months before a user did.

At minimum (2) should land before more parallel feature branches carry migrations.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions