One cleanup button would have deleted three quarters of a photo library
The check could not tell "the file is not there" from "I could not look", and it chose to delete.
A car-services business we are related to has an admin gallery with a button that deletes broken photos. We tested the software around it. The button judged a photo broken when its thumbnail was missing.
The button
The gallery's cleanup button removed a photo permanently: the database row, the original file and the published copy. It chose what to remove by looking for a derived thumbnail, on the idea that a photo with no thumbnail is a broken one.
The confirmation did not even say how many photos would go, because the scan ran after the click.
Why the rule was wrong
Only one of the four upload routes ever makes a thumbnail, so a missing thumbnail was normal. Measured on the live data, 444 of the 588 image rows looked broken. The 588 rows span two related businesses, 576 and 12. One click would have destroyed the originals of three quarters of the library.
Checked against the real storage index, none of the 588 was missing.
Three fixes, one flaw
Each of the first three rounds of fixes repaired one layer and kept the same flaw: when the probe could not tell absent from could-not-check, it deleted. A storage error read as absence. A public bucket with no read policy made a live photo look missing. The client derived two more file keys at delete time without checking them.
The tests did not catch it because the test double let the signing step succeed, which the real service did not.
The fix that replaced the probe
Three rounds on the same idea means a design defect, not a patch. So the fourth change replaced the probe. It asks the database for the source of truth through a read-only function that names every object it would remove, fails if a bucket reads as empty, and keeps a typed confirmation, a refusal above a quarter of the library, and a rule that a row whose public copy is alive is never deleted. Nothing was deleted by the old button.
What to take from it
- Make "cannot tell" fail closed. Ambiguity should never resolve to delete.
- Ask the source of truth. A missing derivative is not a missing original.
- Stop at the third repeat. It is a design problem, so redesign.
Want your destructive actions checked before a customer finds them?
We test the button you hope nobody presses. The first month is a trial.