The QA list nobody wants to read
91% of the bugs that reach a real user are off the happy path everyone tested. So before every ship we run the QA list nobody wants to read — empty states, double-submits, offline mid-action, names with an apostrophe. Here it is, in order.
by Ria P.
The QA list is the least-loved document in the studio. It's the thing that sends a "finished" feature back to the person who finished it, on a Thursday, over something they swear no real user would ever do. They're wrong. Real users do all of it, and more, and they do it on the worst phone in the building. Here's the list nobody wants to read — the one we run before every ship, in the same order, every time.
- Open the empty state first. Every list, table, and dashboard has one, nobody designs it, and it's the very first thing a real new user sees. "No data yet" is a screen, not an afterthought.
- Do the thing twice. Double-click submit. Refresh mid-payment. Hit the back button after checkout and watch what the second charge does. Idempotency is a QA finding before it's a backend feature.
- Pull the network out in the middle of the action. The happy path assumes the request comes back. Real users walk into elevators, tunnels, and basements with one bar, and your spinner spins forever unless someone made it stop.
- Type a name with an apostrophe in it. O'Brien has broken more software than any SQL injection. Then add an emoji, a sixty-character surname, and a trailing space, and see which field quietly mangles it.
- Use it on the worst phone you can find. A slow Android from four years ago, brightness down, font scaled up for someone who actually needs it. The layout that looks fine on the designer's sixteen-inch Mac is not the layout most people get.
- Read every error message out loud. If it says "Something went wrong" or "Error 500," it isn't finished — it's a shrug with a stack trace behind it. The user can't act on a shrug.
- Log in as the account with no permissions, then as the one with all of them. The interesting bugs live at the boundaries: the button that's visible but shouldn't be, the page that 403s with a blank white screen instead of a sentence.
- Enter the numbers that aren't numbers. Zero. Negative. A decimal where you wanted an integer. The quantity 1,000,000. A date in 1900 and a date in 2099. The form that only tested "5" is a form that only works for 5.
None of this is clever, and that's the objection we hear most: "a real user would never do that." The breakdown above is every bug that reached a real user across three projects last year, sorted by what the user was doing when it broke. Nine percent were on the happy path — the part everyone tested. The other ninety-one were somewhere on this list.
The curve above is why we run the boring list before, not after. A bug caught on the QA list costs roughly nothing — a line in a ticket, fixed the same afternoon. The same bug caught by a user in production costs about thirty times as much by the time you've fielded the support email, reproduced it, shipped a hotfix on a Friday you hadn't planned to, and apologised. The list is the cheapest place a bug will ever be.
What we won't do is automate the list away and call it covered. Automated tests are wonderful and we write a lot of them — but a green CI run only tells you the things you thought to check still pass. It tells you nothing about the empty state nobody designed or the error message that says "undefined." The list is a human reading the screen like a suspicious stranger, and no coverage percentage replaces that. We wrote the same thing about security scans: the tool finds what it was told to find, and the real work is the part it can't.
What changed since we started handing this list to clients: the pushback moved earlier. Teams used to argue with QA findings the week before launch, when changing anything is expensive and tempers are short. Now they read the list at the start and build for it — the empty state gets designed, the error copy gets written, the apostrophe gets handled in week two instead of week eleven. The list nobody wants to read turns out to be cheapest when you read it first.