How to Fix Invalid JSON (and Salvage the Broken Parts)
The JSON that took down our Tuesday deploy was about 4,000 lines long and had exactly one thing wrong with it: a trailing comma. JSON.parse didn't mention the comma. It threw Unexpected token } in JSON at position 98241, which pointed at a closing brace roughly a hundred and sixty lines below the actual mistake, because that's how JSON errors work โ they report where the parser finally choked, not where you fed it something bad.
Forty minutes. One comma.
Here's what I wish I'd internalized years earlier, before I'd donated whole afternoons to this: almost every "invalid JSON" error comes from one of five mistakes, and you can fix all five faster than you can decode the stack trace. So this is how to fix invalid JSON without the forty-minute detour โ the five usual suspects, why the error position lies to you, and what to do when a property is so mangled you're better off cutting it out than rescuing it.
The five mistakes behind almost every invalid JSON error
I've kept a rough tally across a couple of years of debugging other people's payloads, config files, and API responses. It's not a formal study โ call it a very opinionated field notebook โ but the same five errors account for nearly everything I see:
- Trailing commas.
[1, 2, 3,]and{"a": 1,}are valid JavaScript and valid Python. They are not valid JSON. This is the number-one offender by a wide margin, and it's the one that took down our deploy. - Single quotes.
{'name': 'Mari'}is what your fingers type on autopilot. JSON strings โ keys and values both โ must use double quotes. Every single one. - Unquoted keys.
{name: "Mari"}reads fine and parses fine in a browser console, so it feels correct. JSON requires the key in quotes too:{"name": "Mari"}. - Comments. You pasted a
// note to selfor a/* config block */from a real config file. JSON has no comments. None. The spec author left them out on purpose, and parsers enforce it ruthlessly. - A missing comma or bracket. Two objects with no comma between them, or one
}short at the end. These are the ones that produce those wildly misleading position numbers.
Notice the pattern. Four of the five are things that are perfectly legal in JavaScript or Python and illegal in JSON. That's not a coincidence โ it's the whole reason this error is so common. JSON looks like a JavaScript object literal, so we edit it like one, and then a strict parser holds us to a stricter rule than our eyes are using.
Why the error position lies to you
Back to my position 98241. The parser wasn't wrong, exactly โ it was honest about the wrong thing. When you leave out a comma between two properties, the parser doesn't stop at the gap. It keeps reading, assuming maybe you meant something valid, and only throws up its hands later when the structure has become impossible. The position it reports is where it hit the wall, which can be many lines past where you actually slipped.
So a raw character offset is close to useless for a big document. What you want instead is a validator that reports the line and column and, ideally, the first point where things went sideways. Drop the payload into the JSON Validator and it points at the exact line and reason rather than a bare offset, which turns "somewhere in these 4,000 lines" into "line 3,180, right here." That one change is most of the forty minutes I could have saved.
A trick that costs nothing: paste the JSON into the JSON Formatter first. Reformatting a minified blob into indented lines makes an unbalanced bracket jump out visually โ the indentation stops matching your mental model exactly where the structure broke. I catch more errors by eye in the formatted version than I ever did staring at position numbers.
When to stop fixing and start amputating
Most of the five are mechanical fixes: swap the quotes, delete the trailing comma, quote the key, strip the comment. Boring, fast, done. But every so often you get a payload where one property isn't wrong in a fixable way โ it's garbage. A value that got truncated mid-write. A field where two log lines collided and produced "amount": 4,"currency". Something no amount of quote-swapping will save.
This is where I think about triage. When a value is corrupt beyond repair and the rest of the document is fine, you don't discard the whole patient to treat one wound โ you isolate the bad property, remove it, and keep everything else working. Throwing away 3,999 good lines because one property is unsalvageable is the JSON equivalent of refusing to treat the other injuries.
Doing that by hand in a 4,000-line file is miserable, so I built the escape hatch into the tools I use. The JSON Viewer and the JSON Formatter both have a Repair & clean action. It makes one tolerant pass over the input: strips comments, converts single quotes to double, quotes bare keys, drops trailing commas โ and when it hits a property whose value it genuinely can't parse, it removes that one property and keeps going instead of failing the whole document. Then it hands you back valid, formatted JSON with a list of everything it changed, including each broken property it had to cut.
That list is the important part, which brings up the one place this can bite you.
The catch: "repaired" is not "correct"
Auto-repair is a debugging aid, not a data-integrity guarantee. It gets you syntactically valid JSON. It does not promise the result means what the original was supposed to mean.
Say the repair drops a mangled "balance" property to salvage the rest. Now you've got clean JSON that parses on the first try โ and no balance. If your code reads that field, you've traded a loud, obvious parse error for a quiet, dangerous undefined three functions downstream. That's a worse bug, because it doesn't announce itself. (I've shipped that bug. Once. You remember the ones that don't throw.)
So the rule I use: repair freely when you're inspecting or exploring an unfamiliar payload, and read the change list every time before you trust the output as data. If the tool tells you it removed a property, that's your cue to find out whether anything depended on it. When the JSON is going back into a system that cares, fix the real error at the source instead of leaning on the repair. For hand-editing that source with a safety net, the JSON Editor validates as you type so mistakes surface immediately, and once it's clean the JSON Minifier compresses it back for the wire.
If you want the fundamentals underneath all this โ what actually counts as valid, and why the rules are so strict โ our guide to what JSON is covers the ground rules, and the JSON formatting guide goes deeper on indentation and readability.
The one-comma takeaway
That Tuesday deploy would've been a two-minute fix if I'd started by reformatting the file and letting a validator point at the line, instead of trying to reason about a character offset in a minified wall of text. Almost every invalid JSON error is one of five small, boring mistakes. Find the real position, fix the mechanical ones, and when a property is beyond saving, cut it out on purpose and note what you cut. Just don't confuse a document that parses with a document that's right.
Got a payload fighting you right now? Paste it into the JSON Viewer, hit Repair & clean, and read what it changed. That last part is not optional.
Try the tools
Frequently Asked Questions
Why is my JSON invalid when it looks fine?
It's almost always one of five things: a trailing comma after the last item, single quotes instead of double quotes, an unquoted key, a // or /* */ comment, or a missing comma or bracket. All five are legal in JavaScript but forbidden in JSON, which is why code that runs fine still fails to parse.
How do I fix "Unexpected token in JSON at position X"?
That position is where the parser finally gave up, not where the mistake is โ the real error is usually a bit earlier. Paste the JSON into a validator that reports the line and column, look just before that spot for a missing comma, a stray comma, or an unclosed string or bracket, and fix that.
What are the most common JSON syntax errors?
Trailing commas and single-quoted strings top the list, followed by unquoted object keys, comments (JSON doesn't allow them), and unbalanced braces or brackets. Copy-pasting from JavaScript, Python, or a config file is how most of these sneak in.
Can you fix JSON with a trailing comma automatically?
Yes. A repair tool can strip trailing commas, convert single quotes to double, quote bare keys, and remove comments in one pass, then re-emit valid JSON. The Repair & clean action in the JSON Viewer and JSON Formatter does exactly this and lists every change it made.
Should I remove a broken property from JSON or fix it?
Fix it if the value is recoverable โ a wrong quote or a stray comma. Remove it only when the value is genuinely corrupt and you don't need it, since dropping a property changes the data. Either way, confirm the salvaged JSON still contains the fields your code depends on.
Marcus Brennan writes for CodeUtilityKit, where the team builds free, privacy-first developer tools that run entirely in your browser. Every guide is written and reviewed by developers who use these tools daily.