CSV Fixer — Repair Broken CSV
Repair a CSV your importer keeps rejecting — quoting, ragged rows, delimiters and line endings
Input
Repaired CSV
What the CSV Fixer does
The import failed on row 4,812 with Error: expected 7 fields, saw 9, you opened the file, scrolled to that row, and it looks completely normal. That is the whole experience of debugging CSV. The format has no schema, no version marker and no header block — every parser has to guess where a record starts and ends from punctuation alone, and the moment one comma appears somewhere the writer did not expect, the guess goes wrong and stays wrong for the rest of the file.
Paste the file on the left, press Fix CSV, and a corrected version comes back on the right. Fields containing a comma, a quote or a newline get wrapped in double quotes; an embedded quote gets doubled the way RFC 4180 asks for; a quoted field that was never closed gets closed; rows that are short or long against the header are squared up; line endings are made consistent; and a byte order mark sitting invisibly in front of your first column name is removed.
A repair is a reading of intent, not a proof. Two of these problems — a stray comma and a genuinely extra column — look identical to any tool, including this one, so read the right-hand panel before you feed the result into anything that writes to a database. If you want to see the corrected file as a grid rather than as text, drop it into CSV to Table; ragged records are far easier to spot when the columns line up on screen.
How to repair a broken CSV file
- Paste or upload the file – Drop the CSV into the left panel, or use Upload for a .csv, .tsv or .txt file on disk. Sample loads a deliberately mangled subscriber export you can experiment with.
- Include the header row – Leave the header in. Most repairs are decided by comparing each record against the number of columns the header declares, so a headerless fragment gives the repair much less to work with.
- Press Fix CSV – The button sits at the top of the input panel and stays disabled while a repair is running, so a slow file cannot be submitted twice.
- Check the field count on the rows you know were wrong – Go back to the row numbers your importer complained about and count the fields. That is a faster check than reading the whole file, and it tells you immediately whether the repair understood the record the way you do.
- Look hard at anything numeric – Long identifiers and codes with a leading zero are the values a spreadsheet damages before the file ever reaches you. A repair can restore structure; it cannot bring back a digit that has already been thrown away.
- Copy or download – Copy puts the corrected text on your clipboard, Download saves it as fixed.csv with the quoting and line endings already normalised.
Pro tip: when a file goes wrong at exactly one row and every row after it is nonsense, suspect an unterminated quote rather than a bad row. The damage starts where the quote opened, not where the parser finally gave up.
Example: a subscriber export that will not import
This is the sort of file that arrives attached to a support ticket — exported once, opened in a spreadsheet, edited by hand, saved again. Four records, and something different wrong with every one of them. On the left is what was pasted; on the right is what comes back.
msisdn,site,plan,rsrp 447700900142,Southwark, London,Unlimited 5G,-92 447700900458,"Leith, Edinburgh,Pay As You Go,-104 447700900773,"Digbeth, Birmingham",Business 200GB← 447700900219,"Cathays, Cardiff",Unlimited "5G" Pro,-88
msisdn,site,plan,rsrp 447700900142,"Southwark, London",Unlimited 5G,-92 447700900458,"Leith, Edinburgh",Pay As You Go,-104 447700900773,"Digbeth, Birmingham",Business 200GB, 447700900219,"Cathays, Cardiff","Unlimited ""5G"" Pro",-88
Eight ways a CSV breaks, and what is really going wrong
Each of these produces an error that points at a symptom rather than a cause, which is why they eat an afternoon. Here is what the parser is actually objecting to, and what a repair can and cannot do about it.
A comma inside a field nobody quoted
msisdn,site,plan
447700900142,Southwark, London,Unlimited 5GThe header promises three columns and this record delivers four, because the parser has no way to know that the comma between Southwark and London is part of a place name rather than a field boundary. Anything holding a comma has to be wrapped in double quotes — "Southwark, London" — and that is the writer's job, not the reader's. It usually appears when someone builds a CSV by joining values with a comma in a loop, which works perfectly until the first address, full name or open comment field goes through it.
A quoted field that never closes
447700900458,"Leith, Edinburgh,Pay As You Go
447700900773,"Digbeth, Birmingham",Business 200GBOnce a field opens with a quote, everything after it is part of that field — commas, newlines, the next thousand records — until a closing quote turns up. So a single missing character on line 12 does not break line 12; it silently swallows the rest of the file and the error surfaces at the very end as something like unexpected end of data. If your row count came back as 3 when the file clearly has 4,000 rows, this is why.
Backslash escaping instead of doubled quotes
447700900219,"Unlimited \"5G\" Pro",false 447700900219,"Unlimited ""5G"" Pro",false
CSV escapes a double quote by doubling it, not with a backslash. The second line is the correct form. Backslash escaping comes from MySQL, from JSON, and from anyone who wrote their exporter by reaching for the escape rule they use every day — and a strict reader treats \ as an ordinary character, so the field terminates early at the quote and everything after it shifts one column left. Worth knowing that some tools accept both, which is exactly how a file gets written this way and only fails later, on someone else's machine.
Ragged rows
msisdn,imsi,iccid,plan,rsrp
447700900142,234150999912345,8901240544102066246,Unlimited 5G,-92
447700900458,234150999967810,8901240544102066253,Pay As You GoThe last record is missing its rsrp value entirely rather than carrying an empty one. Plenty of exporters drop trailing empty fields to save bytes, and plenty of readers refuse to accept the result. The repair pads a short row out to the header width and, where a row is longer than the header, keeps the surplus rather than discarding it — a dropped value is worse than an ugly one, because you will not notice it.
Mixed CRLF and LF line endings
msisdn,plan\r\n 447700900142,Unlimited 5G\r\n 447700900458,Pay As You Go\r\n
A file written on Windows and then partly rewritten on Linux ends up with both endings in it. A reader that splits on \n alone leaves a carriage return glued to the final field of every Windows line, so "Pay As You Go\r" never equals "Pay As You Go" in a comparison and your lookup fails on rows that look identical in every editor you own. RFC 4180 specifies CRLF, but the practical answer is simply to pick one and apply it to every line.
The invisible BOM Excel writes
<U+FEFF>msisdn,imsi,iccid
447700900142,234150999912345,8901240544102066246Choosing CSV UTF-8 (Comma delimited) in Excel prepends three bytes — EF BB BF — that render as nothing at all. Your first column is then named \ufeffmsisdn, so row["msisdn"] comes back undefined while the header visibly says msisdn on screen. It is the single most infuriating bug in this list because every tool you would use to inspect the file hides the cause. The Unicode BOM FAQ explains what the mark is for; for CSV it is pure liability, and the repair strips it.
Semicolons, because the file came from a European locale
msisdn;plan;monthlyCost
447700900142;Unlimited 5G;24,99In locales where the comma is the decimal separator, Excel switches its list separator to a semicolon so that 24,99 stays one number. The file is internally consistent and completely valid — it just is not comma-separated, and a reader hard-coded to a comma sees one enormous column. Notice the second problem hiding underneath: 24,99 is 24.99, and converting the delimiter without converting the decimal separator turns one price into two columns. MDN's Intl.NumberFormat reference is the quickest way to see which locales do this.
A leading zero or a long ID a spreadsheet already ate
msisdn,iccid,accountRef 4.477009E+11,8901240544102066000,4021
Open a CSV in a spreadsheet and it will helpfully treat every column as numeric: 04021 loses its zero, a 19-digit ICCID such as 8901240544102066246 is rounded to 8901240544102066000 because floating point holds about 15 reliable digits, and a long MSISDN is rewritten in scientific notation. Save, and the damage is on disk. This is the one case a repair cannot help with — the digits are genuinely gone. Re-export from the source with those columns typed as text, and open the file with an import dialog rather than a double-click. Worth checking your own writer too: Python's csv module writes whatever string you hand it, which is why it is a safer round trip than a spreadsheet for identifier columns.
If you are looking at an error message that matches none of these, the csv tag on Stack Overflow has years of answers about how the same malformed byte is reported differently by pandas, Excel, Postgres COPY and half a dozen JavaScript parsers. For the longer view of why a format this simple is this fragile, the W3C's CSV on the Web primer is a good hour spent.
When you will reach for this
An import that fails on one row out of forty thousand
Bulk importers tend to reject the whole file for a single malformed record, and the row number they quote is where parsing collapsed rather than where the mistake was made. Repair the file here, then load it into CSV to Table and sort by a column you know should never be empty — a record that was quietly shifted one field left stands out instantly when the values in a column stop looking alike.
A file a customer edited in a spreadsheet and emailed back
Round-tripping a CSV through a spreadsheet is where quoting, delimiters and encoding all get renegotiated without anyone being asked. You get back a file that opens perfectly on their machine and not at all on yours. This is the fastest way to get it back to something portable before you go looking for what actually changed.
CSV assembled by string concatenation
Every codebase has a report endpoint built from values.join(','). It works for months and then someone enters a company name with a comma in it, or a note with a line break, and the export starts producing rows of the wrong width. Use the fixer to unblock whoever is waiting for the file, then fix the writer — a real CSV encoder is a few lines, and it will not be wrong again next quarter.
Getting tabular data ready to convert
Nothing downstream will touch a CSV that does not parse. If the plan is to turn the file into something else, this is the step before that: repair it here, then take it to JSON to CSV or XML to CSV when you need to go the other direction, or to JSON to Table when the source was JSON all along.
Frequently asked questions
What can it actually repair?
Structural problems: fields that need quoting and do not have it, an unterminated quoted field, backslash-escaped quotes that should be doubled, rows that are short or long against the header, mixed CRLF and LF endings, a leading byte order mark, and a file that uses a delimiter other than the one you expected. What it cannot do is invent a value that was never written, or restore digits a spreadsheet has already rounded away.
Will it change my values as well as my structure?
The intent is that only the punctuation around a field changes — quotes added where they are needed, a quote character doubled, a line ending normalised. Cell contents should come through byte for byte. The quickest way to confirm it on a specific file is to pick a row with a distinctive value in it and check that value in the output panel before you use the result.
How does it decide whether my file is comma or semicolon separated?
By looking at which candidate delimiter produces a consistent number of fields per row across the file, not by counting characters. That distinction matters: a comma-separated file full of European place names can easily contain more semicolons than a semicolon-separated one contains commas. If the file has only one or two rows, there is not much evidence to work with, so give it more rows if you can.
My row count is wrong but there are no errors. What happened?
Almost always an unterminated quote. Everything from the opening quote onward is being read as a single enormous field, so the parser reports a handful of rows for a file with thousands. Search the file for an odd number of quote characters on a line — that line is where the damage starts, not where the reader gave up.
Why did my 19-digit ICCID come back as ...066000?
Not from this page — that damage happens upstream. Spreadsheets and many conversion tools route every numeric-looking column through a floating point number, which holds around 15 to 16 reliable digits, so 8901240544102066246 becomes 8901240544102066000 the moment the file is opened and saved. The corrected text here goes straight into the output panel as text and is never re-parsed as numbers, but if the file already arrived rounded, the original digits no longer exist anywhere in it.
Does it handle TSV and pipe-delimited files?
Yes — tab and pipe separated files follow the same quoting rules and break in the same ways, so the same repairs apply. The extension does not matter; paste the text and the delimiter is worked out from the content.
Should I fix the file or fix the exporter?
Fix the exporter, always — this page is for the file that is blocking you right now. If the same export breaks every month, the cause is a writer joining strings with a delimiter instead of encoding them, and no amount of downstream repair will keep up with it. Use the fixer to get unblocked, then go and change the writer while you still remember why.