Two booleans, one word of difference, and a twenty-five second hang that emptied a user's screen.
The screen that emptied itself
The bug report was short and strange: switching from paper trading to a live account wiped the list. Not an error, not a spinner — an empty panel where five broker configurations used to be.
My first guess was a frontend state bug, because that is what an empty list usually means. It wasn't. The list was empty because the backend had quietly decided the user had never authorized anything.
I ended up sitting with this one the way I sit with a 90-minute timer. You don't learn anything in the first five minutes. You learn something at minute forty, when you've stopped guessing and started reading.
One boolean doing two jobs
The system had a flag called `is_active`. Reading the code, it meant this configuration has been authorized — a fact about the user's history. Somebody clicks "authorize", you store a token, the flag goes true, and it stays true forever.
But the same flag was being cleared whenever a connection attempt failed. So "we couldn't reach the broker just now" was being written down as "you were never authorized." Two completely different facts, one variable.
The trigger was an expired token. The renewal path assumed a refresh token found on disk still worked, tried to use it, failed, and then fell through to opening a browser window for the user to authorize manually — from a background job with no browser to open.
Twenty-five seconds of nobody home
That browser request had no way to complete. The callback fired, printed a log line, and the job sat there waiting out a 25-second timeout. Every one of those seconds held a thread.
Three changes ended it. Expired tokens no longer trigger a background connect at all — the config simply reports that the user needs to re-authorize, and the user clicks a button. Connection failures no longer touch the authorization flag. And the adapter now polls for a browser request every half second so it can bail immediately instead of waiting out a timeout nobody will answer.
The user-visible result: the list stays intact, the account keeps saying "authorized", and one extra click is the entire cost. I would rather ask the user to press a button than risk a background job that nobody is listening for.
The part worth keeping
The lesson generalized past this bug: if two states feel like the same state, they probably aren't. Authorized is about the past. Connected is about right now. When you collapse them into one flag, a transient failure gets recorded as a permanent truth.
And a background task that needs a human is not a background task. It's a request for attention that arrived at the wrong address — and the honest move is to admit it failed fast rather than hold the line for twenty-five seconds.
The empty list is gone. What replaced it is a rule: never let a failed connection rewrite a successful authorization.