A run opened before the control plane wrote down where a run came from has no origin, cannot be read back, and took the whole service down with it: the restore refused the row, the process exited, and it did so again on the next start and every one after. One unusable row was an outage with no way out but editing the database by hand. Dev spent this morning that way, and prod would have hit the same wall on its first control-plane deploy.
Applying the schema now drops such a run and makes both columns mandatory, so no later one can look like it. Inventing an origin is still off the table — what changed is the cost of refusing. A run with no origin can never be assigned, because a node cannot be told what it is building, so keeping it bought nothing and cost everything.
With the columns mandatory there is no longer a row shaped like that to read, so the case and its error go away.
The test drives the real migration path: it puts the table back in the old shape, opens a run the way the old version did, restarts, and asserts the readable run survived while the unreadable one did not. Without the migration it fails on the null it used to die on.
A run opened before the control plane wrote down where a run came from has no origin, cannot be read back, and took the whole service down with it: the restore refused the row, the process exited, and it did so again on the next start and every one after. One unusable row was an outage with no way out but editing the database by hand. Dev spent this morning that way, and prod would have hit the same wall on its first control-plane deploy.
Applying the schema now drops such a run and makes both columns mandatory, so no later one can look like it. Inventing an origin is still off the table — what changed is the cost of refusing. A run with no origin can never be assigned, because a node cannot be told what it is building, so keeping it bought nothing and cost everything.
With the columns mandatory there is no longer a row shaped like that to read, so the case and its error go away.
The test drives the real migration path: it puts the table back in the old shape, opens a run the way the old version did, restarts, and asserts the readable run survived while the unreadable one did not. Without the migration it fails on the null it used to die on.
A run opened before the control plane wrote down where a run came from has
no origin, cannot be read back, and took the whole service down with it: the
restore refused the row, the process exited, and it did so again on the next
start and every one after. One unusable row was an outage with no way out but
editing the database by hand. Dev spent this morning that way.
Applying the schema now drops such a run and makes both columns mandatory, so
no later one can look like it. Inventing an origin is still off the table --
what changed is the cost of refusing. A run with no origin can never be
assigned, because a node cannot be told what it is building, so keeping it
bought nothing and cost everything.
With the columns mandatory there is no longer a row shaped like that to read,
so the case and its error go away.
day01
merged commit 5ab2b3597d into %!s()2026-08-12 10:54:39 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
A run opened before the control plane wrote down where a run came from has no origin, cannot be read back, and took the whole service down with it: the restore refused the row, the process exited, and it did so again on the next start and every one after. One unusable row was an outage with no way out but editing the database by hand. Dev spent this morning that way, and prod would have hit the same wall on its first control-plane deploy.
Applying the schema now drops such a run and makes both columns mandatory, so no later one can look like it. Inventing an origin is still off the table — what changed is the cost of refusing. A run with no origin can never be assigned, because a node cannot be told what it is building, so keeping it bought nothing and cost everything.
With the columns mandatory there is no longer a row shaped like that to read, so the case and its error go away.
The test drives the real migration path: it puts the table back in the old shape, opens a run the way the old version did, restarts, and asserts the readable run survived while the unreadable one did not. Without the migration it fails on the null it used to die on.