data integrity 6 min read

One Missing Underscore Sent Someone to Prison for 18 Months

Every developer has shipped a bug where two records that should have been separate got merged, or one record got split into two. Usually you notice in staging. Sometimes a user files a ticket. And sometimes the record lives in a police database, and the person on the wrong end of the match spends 18 months in a cell before anyone checks the underlying data.

A quick note on framing: I’m not going to litigate the specific facts of any one case. The structure is what matters, and the structure repeats. Same failure mode, different jurisdiction, every few years.

The root of it is boring. When one character goes missing, the system does not conclude that this is a different person. It concludes that this is a similar person. That distinction is where everything falls apart.

Underscores Are Load-Bearing

You already know this one. In an identifier, the underscore, the hyphen, and the space all look like separator characters, and systems treat all three completely differently.

SMITH_JOHN and SMITHJOHN are not equal under string comparison. To a human eye scanning a data-entry screen, they’re indistinguishable. So when a clerk drops the underscore, that isn’t a typo in any meaningful sense. It’s the creation of a new person. A human being who does not exist now has a row in the database.

The other direction is worse. Two real people collapse into one during normalization. Legacy systems strip special characters before comparison all the time, usually to make search behave the way users expect. Do that, and KIM_MS and KIMMS become the same key. Two people’s records are now in one folder, and nothing in the schema records that a merge happened.

In a CRM, that’s an embarrassing support ticket. In a criminal records system, someone else’s conviction history is now attached to your name.

There Is No Rollback in Criminal Justice

When you find a bug in production, you revert the commit, ship the patch, post the incident report, and move on. The mental model is that mistakes are reversible and the cost of a mistake is the cost of the fix.

Criminal justice does not work like that. Bad data triggers an arrest. The arrest justifies detention. Detention proceeds to trial. Each stage treats the previous stage as established fact. The prosecutor trusts the police record. The judge trusts the prosecutor’s file. Nobody in the chain re-queries the source and asks whether the original match was sound, because that isn’t anyone’s job.

That’s what makes 18 months the frightening number. It doesn’t mean the bug went undetected for 18 months. It means that for 18 months, nobody doubted it — on the strength of a value a computer returned.

Psychologists call this automation bias, and it’s been studied since the 1990s in aviation and medicine: people defer to a machine’s output over their own judgment, and over other people’s testimony. The defendant can say “that isn’t me” as many times as they like. They are arguing against a match on a screen, and the screen doesn’t have to explain itself.

The Typo Isn’t the Failure. The Design Is.

When these cases surface, the official finding is almost always “data entry error.” One employee gets disciplined. The system is deemed fundamentally sound. Case closed.

From an engineering perspective that reading is nonsense. Typos in human-entered fields are not bugs. They are a constant. They will happen at a predictable rate forever, and a system that assumes otherwise is a system that hasn’t been designed, only assembled.

Here’s what a real design looks like.

Use identifiers with checksums. Credit card numbers have run the Luhn algorithm since 1954 for exactly this reason: a single-digit error produces an invalid number rather than a valid number belonging to someone else. ISBNs do it. IBANs do it. National ID formats in several countries do it. It is the oldest trick in the book and it costs nothing.

Separate fuzzy matches from exact matches in the UI. “This is the person” and “this might be the person” need to look completely different on screen. Most systems dump both into one result list, sorted by score, with no visual distinction. The officer reading that list has no way to know which rows are certainties and which are guesses.

Require two independent factors for identity confirmation. Never resolve a human being from a single name string. This is not a novel idea — it’s how every bank onboards a customer.

Make the dispute path actually load-bearing. When someone says “that isn’t me,” there needs to be a documented procedure that turns that statement into a re-verification of the underlying record. Not a form that goes into a queue. A procedure with a defined outcome.

AI Matching Makes This Harder, Not Easier

Law enforcement agencies worldwide are rolling out AI-driven matching right now: facial recognition, name-similarity scoring, cross-database entity resolution. The pitch is that it fixes exactly the problem I’ve been describing.

Here’s the paradox. AI matching is robust to a missing underscore. It’ll normalize right past it. The problem is that it over-corrects, and it does so invisibly.

String matching has one genuine virtue: it can explain itself. This character equals that character, therefore match. You can print the comparison. A defense attorney can read it. Embedding-similarity matching says 0.87 and stops talking. Similar how? Along which dimensions? Nobody knows, including the people who deployed it.

Old systems failed sharply. Characters differ, no match; characters agree, match. The errors were wrong but legible. New systems fail softly, and soft failures are far harder to contest. The burden of proving your innocence shifts from arguing about a string to arguing about a probability distribution — and courts have no established vocabulary for the second one.

This is exactly the concern behind the EU AI Act’s classification of law-enforcement biometric identification as high-risk, and behind the wrongful-arrest lawsuits filed in Detroit and New Jersey over facial recognition matches. The technology got better at matching before the institutions got better at doubting.

Your Codebase Has the Same Hole

Let’s not pretend this is a story about foreign police departments.

Does your user-merge logic treat lowercased email as a sufficient identity key? Does your billing system resolve customers by name plus date of birth? Does your log pipeline normalize a string and then group everything that matches into one session?

Same structure. Every one of them. The only variable is what a false merge costs.

For a police database, the cost was 18 months of someone’s freedom. For most of what we build, it’s lower. But lower is not zero. Merge two accounts incorrectly and one person’s private data renders on another person’s screen — and if you’re in a GDPR jurisdiction, you’ve just created a reportable breach out of a normalization function nobody reviewed.

People Will Keep Getting It Wrong

The lesson here is not “be more careful with data entry.” People will keep getting it wrong. Human error is not a defect to be eliminated; it is the operating condition you build on top of.

What’s needed is design that prevents bad data from passing silently. That requirement scales with the stakes, and when the output of your system determines what happens to a person’s life, it isn’t optional.

So: in the system you’re building right now, what happens when one character goes missing? If the answer doesn’t come to you immediately, that’s worth an hour this week. The answer exists whether or not you’ve looked at it.

data integrity criminal justice identifiers system design tech trends

Comments

    Loading comments...