An error log nothing was ever written to
Our card routes logged every provider failure to a table that does not exist. The write was wrapped in a catch, as it has to be, so it failed silently — and the errors screen showed nothing, which reads exactly like nothing going wrong.
If something fails when your till talks to a card reader, you want it written down. Not shown to the customer — a provider's raw refusal on a screen at a counter is worse than useless — but recorded, so that somebody can look later and see that it happened eleven times on Saturday.
So the card routes log every provider failure. They have done since the day they were written.
They log it to a table that does not exist.
Why it never made a noise
A failure to log a failure must not itself become a failure. If the logging write throws, and that throw escapes, then a card reader having a bad moment turns into a till that cannot take money at all. So the write is wrapped: try to record it, and if recording does not work, carry on.
Which is right, and which is exactly why nobody noticed. The table name was wrong — the log is called something else and has a different shape entirely — so every single write failed, was caught, and was dropped. Six releases of that.
And the errors screen showed nothing for card. Which reads exactly like "no card errors have happened."
An empty screen is two different facts
This is the thing worth taking away, and it is not really about databases. Nothing on a screen can mean nothing happened, or it can mean nothing is being recorded. Those look identical and they are opposites.
It is the same shape as a sales report that shows no refunds because there were none, versus one that shows no refunds because the refund path stopped writing them. Or a kitchen screen with no tickets because service is quiet, versus one that lost its connection twenty minutes ago.
Anywhere a zero can mean either, it is worth being able to tell — a last-written time, a count of what was looked at, something that distinguishes "quiet" from "deaf".
What we changed
The log now writes to the table the errors screen actually reads, in the shape it expects: repeats collapse into one row with a count, a problem that comes back is marked unresolved again, and it deliberately does not record which venue — a reader being unreachable is not one venue's fault, and a row per venue would bury it.
And there is now a check across the whole codebase: every write must name a table the database actually has. It found exactly one. A read from a missing table throws where somebody sees it; a write that is caught and dropped never does, which is why writes are the ones worth checking.
Nothing was lost, because no card payment has ever been attempted through HelchPOS — card processing is not switched on. But the day it is, those messages start mattering, and they would have gone nowhere.