SyntaxError: Unexpected token } in JSON at position 212 is one of the least helpful error messages a developer sees. It tells you that the JSON is broken, but not why, and the position is a character offset you have to count to.
The good news: almost every JSON error comes from the same short list of mistakes. This guide covers the eight you will hit most often, what the error looks like in JavaScript and Python, and how to fix each one.
Quickest fix: paste your JSON into the JSON Validator. It names the mistake in plain English, shows the exact line and column, and highlights the broken line.
Why JSON is so strict
JSON looks like a JavaScript object literal, but it is a much smaller language. The specification (RFC 8259) allows only:
- objects
{}with double-quoted string keys, - arrays
[], - strings in double quotes,
- numbers,
true,falseandnull.
That's it. No comments, no trailing commas, no single quotes, no undefined. Being strict is what makes JSON portable — every language parses it the same way — but it means small habits from JavaScript or Python break it.
1. Trailing commas
{
"name": "Jane",
"role": "admin",
}
JavaScript, TypeScript and Python all allow a comma after the last item. JSON does not.
-
JavaScript:
Expected double-quoted property name in JSON at position 41 (line 4 column 1)in current Chrome and Node.js; older engines sayUnexpected token } in JSON -
Python:
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes
Fix: remove the comma after the last property or array item.
2. Single quotes
{ 'name': 'Jane' }
Strings and keys must use double quotes ("). Single quotes are the most common mistake when JSON is typed by hand or copied from Python's print() of a dict.
Fix: replace ' with ". If you are producing JSON from Python, use json.dumps(data) instead of str(data) — str() prints Python syntax, not JSON.
3. Unquoted keys
{ name: "Jane", age: 31 }
Valid JavaScript, invalid JSON. Every key must be a double-quoted string.
Fix: wrap each key in double quotes: { "name": "Jane", "age": 31 }.
4. Missing commas
{
"name": "Jane"
"role": "admin"
}
Usually caused by adding a new line to an existing object and forgetting the comma on the line above. The parser reports the error on the second line, which is confusing — the mistake is really at the end of the line before.
Fix: add a comma after "Jane". When an error points to the start of a line, always check the end of the previous line first.
5. Comments
{
// database settings
"host": "localhost"
}
JSON has no comment syntax. Some tools accept “JSONC” (JSON with comments) — VS Code's settings.json and tsconfig.json are examples — but a standard parser like JSON.parse will reject it.
Fix: remove the comments. If your config needs comments, consider YAML or TOML instead — see JSON to YAML.
6. Python and JavaScript values that aren't JSON
{ "active": True, "manager": None, "score": NaN, "extra": undefined }
| Not JSON | Use instead |
|---|---|
True / False (Python) |
true / false
|
None (Python) |
null |
undefined (JavaScript) |
null, or leave the key out |
NaN, Infinity
|
null, or a string like "NaN"
|
NaN is a sneaky one: Python's json.dumps writes NaN by default, producing output that other parsers (including JavaScript's) reject. Pass allow_nan=False to catch it early.
7. Unescaped characters inside strings
{ "path": "C:\new\folder", "quote": "She said "hi"" }
Inside a JSON string, a backslash starts an escape sequence and a double quote ends the string. So \n becomes a newline, \f a form feed — and "hi" closes the string early.
Fix: escape backslashes as \\ and quotes as \":
{ "path": "C:\\new\\folder", "quote": "She said \"hi\"" }
Literal line breaks and tabs inside a string are also invalid; use \n and \t. The JSON Escape tool converts any text into a correctly escaped JSON string.
8. The response isn't JSON at all
SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON
(Older engines: Unexpected token < in JSON at position 0.) If the first character is <, you are not parsing JSON — you are parsing an HTML page. Typical causes:
- the URL is wrong and the server returned a 404 page,
- your session expired and you were redirected to a login page,
- the server crashed and returned an HTML error page.
Fix: log the raw response before parsing it, and check the status code and Content-Type header:
const res = await fetch(url);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const type = res.headers.get('content-type') ?? '';
if (!type.includes('application/json')) {
throw new Error(`Expected JSON, got ${type}: ${(await res.text()).slice(0, 200)}`);
}
const data = await res.json();
A similar case is Unexpected end of JSON input, which means the text was empty or cut off — often an empty response body from a 204 No Content or a request that timed out.
Errors that aren't syntax errors
Some JSON parses fine but still causes bugs:
-
Duplicate keys:
{"role": "user", "role": "admin"}is accepted by most parsers, which silently keep the last value. -
Big numbers: integers above 9,007,199,254,740,991 (253 − 1) lose precision in JavaScript.
1234567890123456789becomes1234567890123456800afterJSON.parse. Send large IDs as strings.
The JSON Validator warns about both, even when the syntax is valid.
A debugging checklist
- Validate the text and go to the reported line.
- If the error is at the start of a line, check the end of the previous line (missing comma).
- If the error mentions
<or<!DOCTYPE, you received HTML — check the request, not the JSON. - Search for
',//,True,None,NaNandundefined. - Once it parses, format it so the structure is easy to review.
Most JSON errors take seconds to fix once you know which of these eight you are looking at.
Originally published at devbrace.com. DevBrace is a set of free developer tools that run entirely in your browser.
Top comments (0)