Skip to content
DevPenh

Common JSON Syntax Errors and How to Fix Them

Trailing commas, single quotes, unquoted keys, raw line breaks and other mistakes that make JSON.parse fail, with fixes.

Last reviewed

JSON looks like JavaScript, but it is much stricter. Most parse failures come from a handful of habits carried over from JavaScript, Python or YAML. This guide lists them with the error messages you are likely to see and how to fix each one. Paste your document into the JSON formatter to get the exact line and column of the first problem.

Reading the error message

Each JavaScript engine words errors differently. For the input {"a": 1,}:

EnvironmentMessage
Chrome / Node.js (V8)Expected double-quoted property name in JSON at position 8 (line 1 column 9)
Python 3.9 (json module)Expecting property name enclosed in double quotes: line 1 column 9 (char 8)

Other browsers and newer Python versions word it differently. The position points at where the parser gave up, which is often just after the real mistake. Look at the character before the reported column as well.

1. Trailing commas

{ "name": "Ada", "active": true, }   ✗
[1, 2, 3,]                           ✗
{ "name": "Ada", "active": true }    ✓

JavaScript and Python allow a comma after the last item; JSON does not. These usually appear after deleting the last property of an object or when JSON is generated by string concatenation. Build JSON with a serializer such as JSON.stringify or json.dumps instead of joining strings.

2. Single quotes

{ 'name': 'Ada' }    ✗
{ "name": "Ada" }    ✓

JSON strings and keys must use double quotes. A frequent source is printing a Python dictionary with print(data) or str(data), which produces Python syntax, not JSON. Use json.dumps(data).

3. Unquoted keys

{ name: "Ada" }      ✗
{ "name": "Ada" }    ✓

Valid in a JavaScript object literal, invalid in JSON. Every key must be a double-quoted string.

4. Comments

{
  // the user's display name   ✗
  "name": "Ada"
}

Standard JSON has no comments. Some tools accept "JSON with comments" (for example VS Code settings and tsconfig.json), but a strict parser such as JSON.parse rejects them. Remove comments, or move the information into a field like "_comment" if you control the schema.

5. Raw line breaks and tabs inside strings

{ "address": "1 Main St
Springfield" }                       ✗
{ "address": "1 Main St\nSpringfield" }  ✓

Control characters (U+0000 to U+001F) must be escaped. Multi-line text needs \n, and tabs need \t. This error often appears when JSON is assembled by hand in a shell script or template.

6. Invalid escape sequences

{ "path": "C:\Users\ada" }      ✗  (\U is not a valid escape)
{ "path": "C:\\Users\\ada" }  ✓

Only \" \\ \/ \b \f \n \r \t and \uXXXX are valid escapes. Windows paths and regular expressions need every backslash doubled.

7. Values JavaScript allows but JSON does not

{ "a": undefined, "b": NaN, "c": Infinity, "d": 0x1F, "e": 012, "f": .5 }   ✗
{ "a": null,      "b": null, "c": null,     "d": 31,   "e": 12,  "f": 0.5 }  ✓

Note that JSON.stringify converts NaN and Infinity to null and drops properties whose value is undefined, while Python's json.dumps writes NaN and Infinity by default, producing output that other parsers reject. Pass allow_nan=False to catch this early.

8. Multiple top-level values

{"id": 1}
{"id": 2}          ✗ as a single JSON document

This is JSON Lines (NDJSON), common in logs and data exports. Parse it one line at a time, or wrap the objects in an array: [{"id": 1}, {"id": 2}].

9. A byte order mark or invisible characters

Files saved by some Windows editors begin with a UTF-8 byte order mark (U+FEFF). JSON.parse rejects it as an unexpected character at position 0, even though the file looks fine. Non-breaking spaces copied from web pages or chat apps cause the same kind of error in the middle of a document. Re-save the file as UTF-8 without BOM, or strip the character before parsing:

const data = JSON.parse(text.replace(/^\uFEFF/, ""));

10. The response was not JSON at all

Unexpected token '<' at position 0 almost always means the server returned HTML — an error page, a login redirect or a proxy message — instead of JSON. Check the HTTP status code and the Content-Type header before parsing:

const res = await fetch(url);
if (!res.ok || !res.headers.get("content-type")?.includes("application/json")) {
  throw new Error(`Expected JSON, got ${res.status}: ${(await res.text()).slice(0, 200)}`);
}
const data = await res.json();

Preventing JSON errors

  • Always generate JSON with a serializer, never with string concatenation or templates.
  • Validate configuration files in CI, for example with jq empty file.json, which fails on invalid input.
  • Use a JSON Schema validator when the structure matters, not only the syntax.
  • When a document parses but behaves differently than expected, compare it with a known-good version using the JSON diff tool.

Part of the API debugging series. Start with How to Debug API Responses: A Practical Workflow.