Unexpected token } in JSON at position 47 is one of the least helpful error messages in everyday programming — it tells you where the parser gave up, not what you actually did wrong. Nine times out of ten, though, the cause is one of a small handful of repeat offenders. Once you know the list, you can usually spot the bug by eye before you even paste it into a validator.
Here's what actually breaks JSON, ranked by how often each one shows up.
1. Trailing Commas
{
"name": "Alex",
"role": "admin",
}
That comma after "admin" is invalid — JSON has no concept of a trailing comma, unlike JavaScript object literals (which do allow it). This is the single most common JSON error, precisely because it's valid in the JavaScript you're probably writing it in, so it doesn't feel wrong. Remove the comma after the last key-value pair or last array item.
2. Single Quotes Instead of Double Quotes
{ 'name': 'Alex' }
JSON requires double quotes, full stop — for both keys and string values. Single quotes are valid JavaScript, valid Python, valid almost everywhere else, and invalid JSON. This one usually shows up when someone hand-writes a JSON example based on muscle memory from another language, or copies a JS object literal and assumes it's already valid JSON.
3. Unquoted Keys
{ name: "Alex" }
Also perfectly legal JavaScript, also invalid JSON. Every key must be a quoted string: "name", not name. This and single quotes are the two errors that make "JSON" and "a JavaScript object literal" feel interchangeable when they're not — JSON is a strict subset of what a JS object literal allows.
4. Comments
{
"timeout": 30, // seconds
"retries": 3
}
JSON has no comment syntax — not //, not /* */. This trips people up because so many JSON-adjacent formats do allow comments (JSONC, used by VS Code's settings.json; JSON5; YAML). If you need a config file with comments, you're not writing plain JSON — you're writing one of those supersets, and it needs to be parsed accordingly, not with JSON.parse().
5. Unescaped Special Characters in Strings
{ "path": "C:\Users\Alex" }
A backslash inside a JSON string has to be escaped as \\, because \ starts an escape sequence (\n, \t, \", \\). A raw Windows file path pasted directly into a JSON string is a very common way this bug appears — C:\Users\Alex needs to become C:\\Users\\Alex. Same applies to unescaped double quotes inside a string (\") and literal newlines inside a string value (must be \n, not an actual line break).
6. Trailing or Leading Data
{ "a": 1 }
{ "b": 2 }
Valid JSON has exactly one top-level value. Two objects back-to-back like this isn't valid JSON — it's two separate JSON documents concatenated, sometimes called JSON Lines (.jsonl) when it's intentional, one JSON value per line. If you meant one document, wrap them: [{ "a": 1 }, { "b": 2 }]. If you meant JSON Lines, you need a parser that reads it line-by-line, not a standard JSON.parse() call on the whole blob.
7. NaN, undefined, and Infinity
{ "score": NaN, "bonus": undefined }
All three are valid in JavaScript, none are valid in JSON. JSON only supports number, string, boolean, null, object, and array — there's no representation for "not a number" or "no value at all." undefined keys are typically just omitted entirely rather than written as null; NaN/Infinity usually need to become a string ("NaN") or a sentinel value your application understands, since JSON's number type can't represent them.
How to Actually Debug a Broken JSON Payload
- Paste it into JSON Formatter — it validates and pretty-prints in one step, and points at the actual problem instead of a bare character offset.
- Check the error line/column against the list above first — most invalid JSON is one of these seven problems, not something exotic.
- If it's config data you're hand-editing and you want comments, switch formats intentionally (JSON5/JSONC) rather than fighting JSON's syntax — don't try to make JSON do something it structurally can't.
- If it's coming from an API response, check whether the API actually returned JSON at all — an HTML error page or an empty body returned with a
200status is a very common source of "invalid JSON" that has nothing to do with syntax.
Quick FAQ
Why does my JSON work in a JavaScript file but fail in a JSON validator?
Because a .js file lets you write a JavaScript object literal — unquoted keys, single quotes, trailing commas, comments all included — which looks like JSON but isn't held to its stricter rules. JSON.parse() and standalone JSON validators enforce the real spec.
Can JSON have duplicate keys? The spec doesn't forbid it, but behavior is undefined — most parsers silently keep only the last occurrence and discard the earlier ones, which can hide a real bug. Treat duplicate keys as invalid in practice even where a permissive parser tolerates them.
Does key order matter in JSON? No — JSON objects are unordered by specification, even though most parsers happen to preserve insertion order in practice. Don't rely on order to carry meaning; use an array if sequence matters.
What's the difference between JSON and JSON5/JSONC? JSON5 and JSONC are supersets that add comments, trailing commas, and unquoted keys back in for human-edited config files — convenient to write, but not interchangeable with strict JSON, since not every JSON parser accepts them.
Related Free Tools
- JSON Formatter — format, validate, and beautify JSON instantly
- CSV to JSON — convert spreadsheet data into valid JSON
- JSON to CSV — go the other direction for spreadsheet-friendly output
- Regex Tester — for validating strings before they ever go into a JSON payload