A customer told us that adding a photo to an album kept failing with a generic error and no useful detail. I went looking for why.
What I believed when I committed it
Reading the upload code, I found a filename rule that only allowed letters, numbers, dots, underscores, and hyphens, rejecting anything else outright. Real photo filenames are full of the characters that rule refused: spaces, parentheses, apostrophes. A file the file browser had just listed as a normal image could still get turned away with “unsupported file type” for no reason a customer could see. I read that rule as an overcautious leftover nobody still needed, and removed it. I committed the change believing I had closed a false rejection and nothing more.
What testing found
Rather than call it done, I built a small harness that runs a batch of filenames, some ordinary and some deliberately adversarial, through the same code path and checks what comes out the other end. The ordinary names all passed, which is what I expected. What I did not expect: some of the adversarial ones passed too. Removing the whole-name whitelist had not just stopped rejecting spaces and parentheses, it had also quietly stopped rejecting a kind of file that should never be treated as a photo, something the old, overcautious-looking rule had been catching as a side effect the entire time. The check had been doing two jobs, and I had only understood one of them.
Closing the gap the fix opened
The fix was not reverting the whitelist, since real filenames still needed to work. It was writing a narrower rule aimed directly at the actual danger the old one had been blocking by accident, while still accepting normal photo names. Run back through the harness, the new rule let every realistic filename through and stopped every adversarial one.
Testing that second fix properly turned up something else, unrelated: rotating a photo whose name had a space in it was already broken in production, silently, because one piece of code read a filename back out of a web-escaped link and handed it straight to a file lookup expecting the real name. It only surfaced because retesting meant actually exercising the code with a realistic filename instead of trusting that the earlier change had worked.
What actually shipped
Both fixes went out together in the next release: the corrected filename rule and the rotation fix, bundled with the original change so the gap between “removed the old rule” and “closed it properly” never reached a live server on its own. The whole sequence, first fix to corrected fix, took about half an hour on a Sunday night. None of it turned out to be the failure the customer had actually hit. That was something else, found later the same night and fixed in the same release. The lesson was not “test more” in the abstract. It was that a rule I could only explain one reason for probably had a second reason I had not found yet, and the only way to find it was to try to break my own fix before I let myself call it finished.