A register of in-flight work assigns each unit an ID. One writer mints them, they are unique, and everything downstream keys off that. The rule is written down.
Two rows ended up with the same ID, a day apart. Nothing complained when the second one was created.
add --id L391 accepted (a row L391 opened the previous day already existed)
land --id L391 landed the FIRST row, left the second in flight
The symptom arrived somewhere else
Nobody noticed at add, because add succeeded. Nobody noticed at land, because land also succeeded and printed a landing.
What surfaced, later, was an unrelated unit being refused by an overlap check, on the grounds that it conflicted with a unit that had already landed. That refusal was correct given the register's contents and wrong about the world: the thing it named as landed had not landed, and the thing that had landed was a different row wearing the same name.
| step | what happened | what was reported |
|---|---|---|
| add | second row created under an existing ID | success |
| land | the older row was landed instead | success |
| a later, unrelated operation | refused against a "landed" unit | a refusal that reads like a real conflict |
Three steps between cause and symptom, and the symptom points at neither.
The rule held. The register did not check it.
This is the part I want to keep, because it is the general case.
The discipline around minting IDs was followed. One writer, no collisions introduced by carelessness; the duplicate came from a queued row nobody had in mind when the second was opened. The humans did the right thing. The register accepted something its own documented invariant forbade, because the invariant lived in prose and in habit, and the code that writes rows never asked.
A constraint that is documented but not checked is enforced by memory. Memory is fine for a while, which is the problem: the first violation is silent, and by the time something visible happens the trail has gone cold.
What went in
Two refusals, at the two places the register can see a violation:
add → refuse an ID that already exists in ANY state (open, landed, abandoned)
land → refuse when two rows share the ID being landed
Both are one condition. Neither is clever. The interesting choice was where: add is the earliest point where the violation exists, so that is where the message is useful, and land is a backstop for rows created before the check existed.
Note that "in any state" is doing real work. Excluding landed or abandoned rows would feel tidy, since those are finished and it is not obvious why they should block a new ID. It would also reintroduce exactly this bug: the collision here was against a row that was merely queued, and the resolution walks over every row regardless of state.
- const clash = rows.filter(r => r.state === 'open').find(r => r.id === id);
+ const clash = rows.find(r => r.id === id); // every row, every state
Two things I would take to any registry
Enforce uniqueness at insert, not at use. At use there is already more than one candidate, and every strategy for picking one (first, newest, most recently touched) is a guess that will be right often enough to hide the problem.
Check the constraint against the whole set, including rows you think are finished. State-filtered uniqueness is not uniqueness. If anything ever resolves an ID without filtering by state, and something always does, then a "finished" row is still a live collision.
The failure mode of getting this wrong is not a crash. It is a correct-looking refusal, somewhere else, for a reason that is true of your records and false of your project.
Top comments (0)