A short text rule intended for one kind of bank charge matched the same letters inside an unrelated word, miscoding a large class of transactions to a plausible account.
Coding transactions from their description text is the most useful automation in a bookkeeping workflow and the easiest one to get quietly wrong.
The situation
A year of bank transactions coded automatically by matching supplier and charge keywords against each row’s description. A short rule existed for a category of bank charge, identified by a three-letter abbreviation that appears in that context.
The coded output looked entirely reasonable. Bank charges came out high, but a busy account generates a lot of them, and nothing on the sheet contradicted the figure.
The pattern
Those same three letters occur in the middle of a common word used in the descriptions of an entirely different, high-volume transaction type. Written as a bare substring match, the rule fired on every one of them.
The result was a large body of transfers coded as bank charges. The failure has three properties that together make it hard to catch:
The output is plausible. Bank charges are expected to exist and expected to be numerous. A larger-than-usual figure invites no scrutiny, unlike a category that should be empty and is not.
The rule is correct in isolation. Tested against the transactions it was written for, it works perfectly. The defect only appears in the presence of data it was never considered against.
Nothing errors. Every row matched a rule and was coded. There is no exception list to review, no unresolved bucket, no failure count — the automation reports complete success.
Two controls prevent it. The first is mechanical: anchor text rules on word boundaries so a match must be a whole word rather than a fragment. Substring rules over free text should be treated as guilty until proven innocent, because the space of words that happen to contain a given sequence of letters is much larger than intuition suggests.
The second is procedural and matters more: review what each rule actually captured, not what it was written to capture. Grouping the coded output by the rule that produced each row turns an invisible defect into an obvious one — a rule for an occasional bank charge that has claimed a large share of the year’s transactions announces itself immediately. This costs one report and finds a class of error that no amount of care in writing the rules will prevent.
Engineering takeaway — Anchor every text rule on word boundaries, and review what each rule actually captured rather than what it was written to capture. An automation that codes every row successfully is not the same as one that codes every row correctly.