My error handling would have blamed my users for a database outage
A ten minute check for anyone whose code catches a broad exception around a service call and shows its message to the user.
In PHP, every database error I can get is a RuntimeException. So is almost every refusal I throw on purpose: please add at least one item, this plan does not include that. From the first commit my controllers caught RuntimeException around service calls and showed the message, which is right for the refusals and quietly wrong for everything else that shares the type.
A review in August read what an unreachable database would have produced. On the invoice form, a validation error made of an SQLSTATE line, on a form the user cannot fix. On checkout, a message saying the payment had permanently failed, from the branch meant for refusals, while the branch that says try again later never ran. On every document page at once, not found, for documents that exist. In the API the same kind of catch would have answered 4xx, which a client library reads as do not retry, so the request a retry would have saved gets dropped.
The fix was to give the refusals a type of their own. A refusal is a message written to be read by the person who caused it, whoever is to blame: unable to save the logo counts, even though that one is our fault. Everything else is logged and answered with a 5xx and one plain sentence. The new type extends the old one, so a catch nobody had narrowed yet kept behaving exactly as before.
A test holds it. It reads every catch block in the web layer from source and fails on a broad catch that quotes the exception message. It also asserts it looked at more than forty of them, because a scan that matches nothing reports a pass.
The check for your stack: grep your controllers for catches of the broadest runtime error your language has, and for each one ask what the user sees if the database is down at that line. If the answer is the exception message, you are showing your outage to someone as their mistake.
Which exception type in your stack is doing two jobs?
Replies