Skip to main content
Back to all posts

Web Development

7 Common JSON Errors and How to Fix Them

The 7 JSON errors that break parsers every day — trailing commas, single quotes, unquoted keys, comments, bad brackets, wrong types — with the exact fix.

MM H Tawfik9 min read

Most "invalid JSON" errors are not subtle. They are the same six or seven mistakes, repeated, almost always caused by JavaScript habits leaking into a format that is far stricter than JavaScript. JSON is defined by RFC 8259 and the byte-identical ECMA-404, and that grammar fits on one page. If your payload does not match it exactly, the parser throws — no warnings, no autocorrect.

This is a fix-list. For each error you get the invalid JSON, the exact error message a strict parser (V8's JSON.parse, the engine behind Node and every browser) produces, and the corrected version. For the broader model — validation layers, schemas, formatting, streaming — read the complete JSON validation and formatting guide. This post stays narrow: the errors, and how to kill them.

1. Trailing commas (the #1 error)

A trailing comma is a comma after the last element of an array or the last property of an object. JavaScript allows it. JSON forbids it — RFC 8259 §4 defines an object as members separated by commas, with no comma permitted before the closing } or ]. This is the single most common JSON syntax error, and it comes straight from copy-pasting JS object literals.

Invalid:

{
  "name": "toolk",
  "tags": ["json", "free", "fast"],
}

Parser error:

Expected double-quoted property name in JSON at position 53 (line 4 column 1)

The message is misleading on purpose: after the comma, the parser expects another property and instead hits }. Delete the comma after the last value.

Fixed:

{
  "name": "toolk",
  "tags": ["json", "free", "fast"]
}

The same rule applies inside arrays — [1, 2, 3,] is invalid; [1, 2, 3] is correct. If you genuinely need trailing commas (and comments), you are using JSON5 or JSONC, not JSON, and you need a parser that opts into them.

2. Single quotes instead of double quotes

JSON strings — including every object key — must use double quotes. RFC 8259 §7 defines a string as characters wrapped in "...". Single quotes are valid in JavaScript and Python but are never valid JSON.

Invalid:

{'name': 'toolk'}

Parser error:

Expected property name or '}' in JSON at position 1 (line 1 column 2)

The parser sees ' where it requires " and gives up immediately at the key. Replace every single quote with a double quote.

Fixed:

{"name": "toolk"}

A common trap: you print() a Python dict and paste the output. Python renders strings with single quotes, so the result is never valid JSON. Use json.dumps(obj) in Python (or JSON.stringify in JS) to produce a spec-compliant string instead of relying on the language's repr.

3. Unquoted object keys

Every key in a JSON object is a string, and every string needs double quotes. There are no bare identifiers. JavaScript object literals allow {name: "x"}; JSON requires {"name": "x"}.

Invalid:

{name: "toolk", version: 2}

Parser error:

Expected property name or '}' in JSON at position 1 (line 1 column 2)

The parser reaches the unquoted name and, because a key must open with ", rejects it at the first character. Quote every key.

Fixed:

{"name": "toolk", "version": 2}

Numeric-looking keys are still strings: {1: "x"} is invalid; {"1": "x"} is correct. The value 2 above stays unquoted because it is a number — only keys and string values take quotes.

4. Comments (not allowed in JSON)

JSON has no comment syntax. None — not //, not /* */, not #. RFC 8259 lists exactly six value types (object, array, string, number, boolean, null) and nothing else; Douglas Crockford removed comments deliberately because people abused them to carry parsing directives. Hand-written config files are where this bites hardest.

Invalid:

{
  "port": 8080, // default port
  "debug": false
}

Parser error:

Unexpected non-whitespace character after JSON at position 23 (line 2 column 18)

Once the parser finishes a token, anything non-whitespace that is not valid grammar is rejected. Remove the comment. If you need to keep a note in the data, add a real string field.

Fixed:

{
  "port": 8080,
  "_comment": "8080 is the default port",
  "debug": false
}

If you control the file format and want comments, switch to JSONC (VS Code's tsconfig.json, settings.json) or YAML — both support // or #. But the moment a strict JSON.parse touches it, comments must be gone. See JSON vs YAML vs XML for when to pick a format that does allow comments.

5. Missing or mismatched brackets and braces

Every { needs a matching } and every [ needs a matching ], correctly nested. A dropped or swapped bracket is the error most likely to hide deep in a large payload, because the parser fails at the point where the structure becomes impossible — not where you made the typo.

Invalid (an array opened with [, closed with }):

{
  "items": [1, 2, 3}
}

Parser error:

Expected ',' or ']' after array element in JSON at position 19 (line 2 column 19)

The parser is inside an array and expects either another element (after a comma) or ]. It found }. Close the array with the matching bracket.

Fixed:

{
  "items": [1, 2, 3]
}

The same class of error covers a missing closing brace at the end of a document (Unexpected end of JSON input) and a stray extra one. Pretty-printing the payload makes the imbalance visible — indentation that never returns to column zero is the tell. A formatter that reports the exact line and column turns a 5,000-line hunt into a one-second jump.

6. Wrong value types

JSON values are limited to the six types in the spec. Several JavaScript "values" are not JSON values at all, and JSON's number grammar (RFC 8259 §6) is stricter than most people expect: no leading zeros, no leading +, and a digit is required on both sides of the decimal point.

Invalid — undefined, NaN, and Infinity are not JSON:

{"a": undefined, "b": NaN, "c": Infinity}

Parser errors (you hit the first one first):

Unexpected token 'u', "{"a": unde"... is not valid JSON

NaN and Infinity fail identically (Unexpected token 'N' / Unexpected token 'I'). JSON has no concept of any of them — use null where you mean "no value".

Invalid — leading-zero and bare-decimal numbers:

{"price": 01, "ratio": .5}

Parser error:

Unexpected number in JSON at position 12 (line 1 column 13)

01 is rejected because RFC 8259 §6 forbids leading zeros, and .5 is rejected because a number must have an integer part before the decimal point. Write them as 1 and 0.5.

Fixed:

{"a": null, "b": null, "c": null, "price": 1, "ratio": 0.5}

Note that JSON.stringify in JS silently converts NaN, Infinity, and -Infinity to null, and drops undefined properties entirely. That is why round-tripping numeric data through JSON can quietly lose fields — a frequent "missing field" bug. To validate that a parsed object has the shape you expect (not just valid syntax), generate a contract with the JSON Schema generator.

7. Unescaped special characters in strings

Inside a JSON string, certain characters must be escaped: the double quote \", the backslash \\, and all control characters including literal newlines and tabs. RFC 8259 §7 requires control characters (U+0000–U+001F) to be written as escape sequences — a raw newline pasted into a string is illegal.

Invalid (a real line break inside the string):

{
  "message": "line one
line two"
}

Parser error:

Bad control character in string literal in JSON at position 22 (line 2 column 21)

Replace the literal newline with \n. The same applies to a stray " (use \") or a Windows path's \ (use \\, or C:\\Users\\me reads as an invalid escape).

Fixed:

{
  "message": "line one\nline two",
  "path": "C:\\Users\\me",
  "quote": "She said \"hi\""
}

Bonus: the big-integer precision trap

This one does not throw — which makes it the most dangerous error on the list. JSON numbers have no defined precision, and JavaScript parses every JSON number into a 64-bit IEEE 754 double. Integers above 2^53 − 1 (9007199254740991) silently lose precision:

JSON.parse('{"id":9007199254740993}').id
// => 9007199254740992   ← off by one, no error

If you move Postgres BIGINT keys, Twitter/X snowflake IDs, or any 64-bit integer across a JSON boundary, this bug is waiting. The fix every major API uses: serialize large IDs as strings — "id": "9007199254740993" — so the bytes survive the round-trip untouched.

How to debug fast

Reading a stack trace to find a comma is wasted time. Paste the payload into the JSON formatter — it runs 100% in your browser, so nothing is uploaded — and it pretty-prints the structure and highlights the first error with the exact line and column. The fix is almost always one of the seven above:

  1. Expected double-quoted property name → trailing comma (or a missing key after a comma).
  2. Expected property name or '}' → single-quoted or unquoted key.
  3. Unexpected non-whitespace character after JSON → a comment, or trailing garbage after the document.
  4. Expected ',' or ']' / Unexpected end of JSON input → mismatched or missing bracket/brace.
  5. Unexpected token 'u'/'N'/'I'undefined, NaN, or Infinity where you need null.
  6. Unexpected number → a leading zero (01) or a bare decimal (.5).
  7. Bad control character in string literal → a raw newline or tab inside a string; escape it as \n / \t.

Once it parses cleanly, the rest of the JSON workflow is routine: compare two payloads with the JSON diff, lock down the shape with the JSON Schema generator, translate to or from config with the JSON ↔ YAML converter, or import spreadsheet data through the CSV ↔ JSON converter. The full set lives in the tools directory.

TL;DR

Almost every "invalid JSON" error is one of seven JavaScript habits that JSON does not allow: trailing commas, single quotes, unquoted keys, comments, mismatched brackets, non-JSON values (undefined/NaN/Infinity/01/.5), and unescaped characters in strings — plus the silent big-integer trap, where IDs above 2^53 lose precision and never throw. JSON's strictness, defined by RFC 8259 and ECMA-404, is the feature: keys and strings in double quotes, no trailing comma, no comments, only the six value types, every control character escaped, and 64-bit IDs sent as strings. When in doubt, paste it into the JSON formatter and let the line-and-column error point straight at the fix.