Every API you call and every config file you read eventually hands you a JSON document. And every so often, that document refuses to parse — throwing a cryptic SyntaxError with a line number that points nowhere useful. JSON has a deliberately tiny grammar, and that strictness is exactly why it’s reliable. The downside is that nearly every mistake trips the parser.

Why JSON is stricter than JavaScript

A lot of JSON in the wild is actually written as if it were JavaScript object-literal syntax. It’s not. JSON is its own format, defined independently in RFC 8259 and ECMA-404, and it accepts a much smaller set of productions. JavaScript lets you write { a: 1 }, leave trailing commas, and sprinkle comments. JSON forbids all three.

The trade-off is intentional: a parser that only has to handle one narrow grammar is fast, safe, and unambiguous across every language ecosystem. When you understand the rules, the errors become predictable.

1. The trailing comma

The single most common mistake. The last item in an array or object must not be followed by a comma.

{
  "name": "ada",
  "role": "admin",
}

Error: Unexpected token } / JSON Parse error: Unexpected comma / JSON.parse: unexpected non-whitespace character.

Fix: remove the comma after "admin".

2. Single-quoted strings

JSON strings use double quotes only. Single quotes are a JavaScript convenience, not a JSON feature.

{ 'name': 'ada' }

Error: Unexpected token ' at position 2 / Unexpected single quote.

Fix: 'name': 'ada' becomes "name": "ada".

3. Unquoted keys

Object keys must be double-quoted strings, not bare identifiers.

{ name: "ada" }

Error: Unexpected token n / Expecting property name enclosed in double quotes.

Fix: wrap the key in double quotes: "name": "ada".

4. Comments

JSON has no comment syntax at all — not // line comments, not /* block comments */. This trips up anyone moving between JSON and JSON5 or TypeScript config files.

{
  // admin user
  "name": "ada"
}

Error: Unexpected token / / Unexpected token //.

Fix: delete the comment, or move the explanation into a sibling documentation field like "description": "admin user".

5. Control characters in strings

A literal newline, tab, or raw backspace inside a string is illegal. JSON requires escape sequences (\n, \t, \r, \b, \f) for control characters below U+0020.

{ "bio": "line one
line two" }

Error: Bad control character in string literal / Invalid character.

Fix: escape the line break as \n: "bio": "line one\nline two".

6. The BOM (byte order mark)

Files saved as UTF-8 from some editors get a three-byte BOM prepended (EF BB BF). RFC 8259 explicitly states that the byte order mark is optional but parsers in the wild vary — many JavaScript and Go parsers reject it outright, while others quietly tolerate it.

Error: Unexpected token U+FEFF / Unexpected non-whitespace character before JSON data, often at position 0 with no visible cause.

Fix: strip the BOM when saving, or run the file through a UTF-8 normalizer before parsing. In Node you can detect it: if (buf[0] === 0xEF && buf[1] === 0xBB && buf[2] === 0xBF) buf = buf.subarray(3).

7. The floating hex literal

JSON numbers are stricter than they look: they support decimals, exponents, and a leading minus, but not leading +, not leading zeros (0123), and not hex literals.

{ "port": 0x1F90 }

Error: Unexpected number / Unexpected token x.

Fix: write the decimal value: "port": 8080.

Let the tooling catch it for you

You can read RFC 8259 cover to cover, but at 2am you don’t want to be counting quote marks. The fastest path to a clean parse is to paste the document into a JSON formatter and validator that flags the exact offending character and shows you the corrected structure side by side. A good validator surfaces every one of the seven errors above in under a second, so you can stop hunting and start shipping.