The Save Button That Was Only Pretending

On April 28, I was tracing reports about comments that would not stay saved. Someone would write a note on an account, press Save, and see the page behave as if everything had worked. Then they would reload the page. The note was gone.

That is a particularly frustrating kind of problem because the person using the page has already done their part. They typed the words. They pressed the button. The page gave them a reassuring answer. Then the work disappeared anyway.

At first, I looked in the wrong place. A comment that vanishes after a page reload sounds like a refresh problem. Maybe an old copy of the page was hanging around. Maybe the person had missed the button. Maybe the comment was there, but the screen was not showing it. Those were reasonable things to check, but they did not explain what was happening. Each check of the stored record showed the same thing: it had not changed.

The cost was not a dramatic crash that forced everyone to stop working. It was quieter and, in its own way, more wearing. Customers and staff could spend time entering comments, changing an email address, setting a flag, changing a password, or deleting a record. The page thanked them for it. Nothing stuck. It also cost time because the first explanations sounded so ordinary that they pulled attention toward the screen instead of the actual change underneath it.

The cause was a setting called a dry run. That sounds technical, but it means a practice pass. Think of laying out ingredients, measuring everything, and even reading the recipe aloud, but never putting the cake in the oven. The system went through almost all the motions of an edit. It built the instruction. It returned the usual success message. It skipped the one step that makes the change real.

One line near the top of a file had been set to false. With that setting false, the account page could handle around 60 different requests, most of them changes, without saving any of them. Comments were only the first thing people noticed. The same setting affected actions such as changing an email address, changing a password, flagging an account, and deleting a record.

The setting had been put there for a sensible reason. Back in October 2023, someone was working on a change locally and did not want to make real changes while testing the surrounding work. In the same session, two temporary safeguards were put in place. One made errors easier to see. The other prevented real edits. Both are understandable ways to work carefully while trying something out.

Then the work was parked for about two and a half years.

When it was picked up again, there was a cleanup before it was merged on April 24, 2026. The first temporary safeguard was found and removed. The second was missed. That was not because anyone ignored the idea of cleanup. The cleanup note even said that old debugging material from October 2023 was being restored. The problem was that the two temporary changes lived far apart in a very long file. One was near line 10. The other was around line 2160.

That distance matters more than it sounds. If you put two sticky notes on opposite ends of a 2,000 page book, you may remember taking one out and still forget the other exists. Two and a half years is long enough for a perfectly clear memory of what was temporary to turn into a blank spot.

The branch was merged on April 24. The release on April 28 sent the missed setting into production. A fix went out at 22:03 that same night. The repair itself was tiny. False became true.

What made this hard was not the repair. It was the silence. The page was designed to say success when the process reached its normal end. In this case, its normal end did not include saving anything. There was no error message, no obvious warning, and no loud signal to tell us that a person had done work for nothing. The first dependable signal came from a customer who noticed a comment had vanished.

I came away with a much plainer rule than a list of technical fixes. A button is not proof that something happened. A cheerful message is not proof either. The proof is the result you can see afterward.

That applies far beyond software. If a bookkeeper says an invoice was sent, check that it reached the customer. If a new employee is told their access is ready, have them sign in. If you set up an automatic payment, look for the first payment to clear. It is not distrustful to check the result. It is how you protect the work that led up to it.

There is also a lesson about temporary workarounds. They are easy to remember while they are fresh. They become much harder to see after a busy week, let alone after years. When I make a temporary change, I want it written down with its companions. Not just, “remember to undo this,” but a short list of every switch changed for that piece of work. A list is better than memory because it still knows what happened after the person who made it has moved on to something else.

The rule that stuck is plainer than any checklist: a success message proves the code reached its normal exit, not that the write happened. The check that would have caught this on day one instead of four days and a customer’s vanished comment later is the same one that would catch it now: read the changed value back after the save, instead of trusting the page that told you it worked.