---
title: "Two Patches Shipped and Came Back Within Three Hours, So I Stopped Patching"
canonical: https://dxdev.com/blog/2026-09-04_one-revert-then-the-real-fix/
datePublished: 2026-09-04
---
A staff admin page has an edit control for moving a customer account onto a different configuration, the kind of change that touches a schedule format, a set of category mappings, and every downstream report that reads them back out. It had always run through an older, narrower code path, one that had never been pointed at the platform's actual migration engine, the same engine used elsewhere for bulk moves. Wiring it up should have been simple. It went out in two patches and came back in a single revert, all within a few hours.

## The first ship, and the one that broke it

The first patch wired the control to the real migration engine: a preview step that shows exactly what will change with nothing written yet, and a separate confirm step that commits it. Shipped clean.

Thirty-five minutes later, a second patch added the piece the preview needed to actually render: a shared dialog library, pulled in for the first time on that admin page. Loading it meant loading its base stylesheet too, and that stylesheet's global resets collided with the page's existing layout, but only on richer accounts, the ones with a full sidebar and a structure table rendering alongside the edit controls. The pre-ship check had only been run against a thin, mostly-empty test account. It never saw the collision, because there was nothing on that account for the reset to visibly break.

## One revert, not two patches surviving

Both patches got pulled back together, in a single revert. Reverting only the styling change would have left the configuration-change control pointed at a preview dialog that needed CSS that had just been removed, so on a real account it would have silently done nothing at all, no error, no result, just a control that didn't respond. Taking both back was the only version of "undo" that left the page in a state that actually worked.

## The rebuild, same afternoon

The rebuild kept the same shape, the real migration engine, a preview then a confirm, but rendered the report inside a dialog widget every other edit control on that page already used. No new library. No new stylesheet. Nothing added to the page that wasn't already there. A missing or malformed confirm flag meant the action was always treated as a preview and never wrote anything.

Independent review, run before any of it shipped again, caught three more things before any of it shipped again:

- A filename problem: the freshly compiled bundle reused the exact filename an earlier, reverted attempt had used, with different bytes underneath it. A browser holding the old cached copy would never know to fetch the new one.
- A comparison bug: the check for whether an account needed the guarded migration path compared a stored value case-sensitively against a lowercase constant, so an account whose value happened to be stored in a different case would fall through to the old, untested path instead.
- A messaging bug: the confirmation screen said the conversion was complete even when the account write had succeeded but a secondary step, moving a folder of photos, had failed and returned a warning. A customer could land on a converted account with a page that said everything worked while some of their content was missing.

## The bug that wasn't a bug

Verification then reproduced the exact error the whole rebuild existed to eliminate, thrown from code that plainly didn't contain what it was complaining about. I got the explanation wrong the first time. A 231-line source rewrite had landed as a two-line change in the compiled bundle, and I read that as proof the bundle hadn't actually recompiled, so I withdrew the ship recommendation and had the build re-verified byte for byte before trusting it again. That reasoning didn't hold up: a minified bundle collapses to one line, so any full rewrite of it will always show as a two-line diff whether or not the content actually changed. The real cause had nothing to do with the compile. An earlier same-day attempt had compiled to that exact same output filename with completely different bytes inside, and the browser doing verification still had that earlier file cached. Because the filename hadn't changed, it never asked for a fresh copy, and it kept quietly running the old, broken version against the new server code. Pulling the served file directly and checking it byte for byte showed the code had been right all along. Bumping to a filename nothing had ever used, and confirming that match again, ended it. Not a defect in the fix. A collision in what the fix was named, and a bad tell on my part that treated a diff artifact as evidence.

## The bug that showed up four days later

The tool sat, reviewed and ready, until the first real run against an actual account: the first attempt to write anything for real, not a preview. It aborted immediately, claiming another conversion was already running against that account. Nothing else was running.

Two separate bugs stacked on top of each other. The locking call itself required conditions that were never actually true in this code path, so it returned an error every single time regardless of whether anything else was running. Separately, the code reading that result treated every non-success code as the same thing, contention, when only one specific code actually means that. A real bug had been diagnosed as a busy lock because nobody had checked which failure code had actually come back. Fixing the lock call and the way its result was read let the same real account run cleanly, with nothing written until confirm, and nothing left ambiguous when it was.

The tool merged into the main branch a few days after the first ship-and-revert day, on the far side of a rebuild, three found-in-review bugs, one cache collision mistaken for a regression, and one locking bug mistaken for a concurrent run. None of those were the bug the original patches shipped with. They were the bugs waiting behind it, the kind that only show up once you stop patching around the edges and build the thing you can actually trust.
