Why Your JSON Won't Parse: 8 Mistakes and How to Fix Them
JSON is supposed to be the simple format. It has six data types and a grammar that fits on a business card. And yet "Unexpected token" errors are among the most common things developers search for. The reason is that JSON looks exactly like JavaScript, so we write it with JavaScript habits, and JSON is much less forgiving.
Here are the eight mistakes I see most often, roughly in order of how much time they waste.
1. The trailing comma
{
"name": "Ada",
"role": "admin",
}
JavaScript, Python and most modern languages are fine with that last comma. JSON is not. Chrome reports something like Expected double-quoted property name, which is confusing until you realise the parser saw the comma and expected another key to follow. Delete the comma.
This one sneaks in when you remove the last item from a list by hand. If you edit JSON config files regularly, it's worth turning on your editor's JSON validation so it underlines the problem immediately.
2. Single quotes
{'name': 'Ada'}
JSON strings and keys must use double quotes. Single quotes usually appear when someone prints a Python dictionary with print(data) instead of json.dumps(data). Python's repr output looks almost like JSON but isn't. The fix belongs at the source: serialise with a proper JSON library rather than converting quotes with search-and-replace, which breaks as soon as a value contains an apostrophe.
3. Unquoted keys
{name: "Ada"}
Valid JavaScript, invalid JSON. Every key needs double quotes, even simple ones.
4. Comments
Douglas Crockford, who popularised JSON, deliberately left comments out so people wouldn't use them for parsing directives. That's why your tsconfig.json works with comments (TypeScript uses a relaxed parser called JSONC) but JSON.parse rejects the same file. If you need comments in configuration, consider JSONC, JSON5, YAML or TOML, and make sure whatever reads the file supports that format.
5. NaN, Infinity and undefined
JSON numbers must be finite, and there is no undefined. JavaScript's JSON.stringify quietly turns NaN and Infinity into null and drops keys whose value is undefined. Python's json.dumps, on the other hand, happily writes NaN by default, producing output that other languages refuse to read. If you work in Python, pass allow_nan=False to catch this early.
6. The truncated document
Unexpected end of JSON input means the parser ran out of text before every bracket was closed. Usually the JSON isn't malformed so much as incomplete: a log line was cut at a maximum length, a network response was interrupted, or you only copied part of it from the terminal. Check the end of the text before hunting for a missing brace in the middle.
A related cousin is Unexpected token < in JSON at position 0. That's not JSON at all. It's an HTML page, almost always an error page or a login redirect, being parsed as if it were your API response. Log the raw response body and the status code and the cause is usually obvious.
7. Invisible characters
Copying JSON out of a chat app, a PDF or a word processor can bring along "smart" curly quotes, non-breaking spaces or a byte-order mark at the start of the file. The text looks perfect but won't parse. If the error points at a spot where nothing looks wrong, retype the quotes on that line or paste the text into a plain-text editor first.
8. Large numbers losing precision
This one doesn't cause an error, which makes it worse. JavaScript numbers are 64-bit floats and can only represent integers exactly up to 253 − 1 (about 9 quadrillion). A 64-bit database ID like 1234567890123456789 silently becomes 1234567890123456800 after JSON.parse. Twitter famously hit this and started returning IDs as strings too (id_str). If your IDs might exceed that range, send them as strings.
A quick debugging routine
- Paste the text into a JSON formatter and read the line and column in the error.
- Look at that line and the line before it. The real mistake is often one token earlier than the reported position.
- Check the first and last characters. Is it actually JSON, and is it complete?
- If two payloads behave differently, format both with sorted keys and compare them in a diff checker.
Nine times out of ten the problem is a comma or a quote. The tenth time it's an HTML error page, and that's a much more interesting bug.
Pretty-print, validate, minify and sort JSON with readable error messages.
Open the JSON Formatter & Validator