From CSV Chaos to Clarity: Deterministic Cleaning Heuristics That Actually Work
Delimiter sniffing, encodings, quoted commas, mixed types, duplicate headers — the real CSV failure modes and the deterministic heuristics that fix them.
CSV is a "simple" format with no enforced standard, which means every CSV you've ever received is a small adventure. After building a parser that accepts arbitrary business exports — CSV, TSV, XLSX, JSON, JSONL, XML, YAML — we've catalogued the failure modes and, more importantly, the deterministic heuristics that fix them without human babysitting. Here's the field guide.
Failure Mode 1: The Delimiter Lottery
Comma-separated except when it's semicolon-separated (most of Europe, where the comma is the decimal separator), tab-separated (database exports), or pipe-separated (someone's clever idea). The heuristic: sniff, don't guess. Take the first few non-empty lines, count candidate delimiters per line, and pick the candidate that (a) appears most consistently across lines and (b) yields more than one column. A comma count that swings from 3 to 7 to 0 across lines means quoted fields; a stable count of 4 means a real delimiter. Papa Parse does this automatically — this is why you use a battle-tested parser instead of split(',').
Failure Mode 2: Encoding Landmines
The file was saved in Windows-1252, your parser assumes UTF-8, and now customer names contain Müller. Three deterministic defenses: check for a BOM (byte order mark) first; attempt strict UTF-8 decoding and fall back to Windows-1252 on failure; watch for the telltale mojibake patterns (é, ’ — the latter is a Windows "smart quote" round-tripped through UTF-8) and re-decode when their density crosses a threshold. Never silently accept mojibake into a dataset; it corrupts grouping keys invisibly.
Failure Mode 3: Quoted Commas and Embedded Newlines
"Smith, John",42,"New\nYork" is one row, three fields — and it destroys every line-based parser. This is the case where hand-rolled parsing dies: quote-aware state machines are the only correct answer, and they must handle escaped quotes ("") inside quoted fields too. If your parser doesn't track "am I inside quotes" as it scans characters, it isn't a CSV parser; it's a bug generator.
Failure Mode 4: Mixed Types in One Column
A quantity column containing 12, 7, about 10, N/A, 4. Naive type inference sees mostly strings and declares the column text; every downstream sum is zero or NaN. The heuristic that works: majority-vote typing. Attempt to parse each non-empty cell as a number (after stripping currency symbols, thousands separators, and parenthesized negatives); if ?90% parse, the column is numeric and the failures become missing values. The same rule applies to dates. Combined with null-token normalization — mapping N/A, -, null, empty strings to true missing values before inference — this recovers most real-world columns.
Failure Mode 5: Duplicate and Missing Headers
Two columns both named amount (a join artifact), or the dreaded unnamed column. Deterministic handling: deduplicate by suffixing (amount_2) rather than overwriting — silently collapsing two columns into one is data loss. Name missing headers positionally (column_4) and flag them, because unnamed columns correlate strongly with export problems worth knowing about. And detect the "header row is actually a data row" case: if the first row parses as the same types as the rest of the column (all numbers, plausible dates), the file probably has no header at all.
The Meta-Principle
Every heuristic above shares a shape: inspect the data, apply a fixed rule, report what you did. No ML magic, no silent mutation. Cleaning steps that can't explain themselves can't be trusted, and cleaning steps that can't be reported can't be audited. The goal isn't a parser that never fails — it's one whose failures are loud, whose fixes are deterministic, and whose output includes a record of every assumption it made. That record is the difference between "the chart looks right" and "the chart is right." And if you ever doubt the stakes, remember that every one of these failure modes ends the same way when ignored: a plausible-looking number, presented with confidence, that is simply wrong.