Common JSON Errors and How to Fix Them
· by Andergrove Software
Unexpected token } in JSON at position 24 tells you something broke, but not
what, and not why. The good news: almost every JSON parse error you will ever see comes from
the same handful of mistakes. This is a field guide to those mistakes — what the error looks
like, what actually caused it, and the one-line fix.
If you just want the answer, paste your JSON into the JSON Validator: it points at the exact line and runs entirely in your browser, so private payloads stay private.
JSON is not JavaScript
Most JSON errors happen because JSON looks like a JavaScript object literal but follows much stricter rules:
- Every key must be quoted, with double quotes.
- Strings use double quotes only. Single quotes are a syntax error.
- No trailing commas after the last item of an object or array.
- No comments. Not
//, not/* */. - No
undefined,NaNorInfinity. Onlynullexists. - One top-level value per document.
Anything a copy-paste from JavaScript source might carry — comments, single quotes, bare keys, a trailing comma left by a formatter — breaks a JSON parser.
The top offenders
1. The trailing comma
{ "name": "test", "size": 42, }
The error: Unexpected token } in JSON at position 30 (Chrome/Node) or
Expecting property name enclosed in double quotes (Python). The parser sees the
comma and expects another entry; the closing brace arrives instead. Fix:
delete the comma after the last item. This is the single most common JSON error, because
JavaScript and most linters happily accept trailing commas.
2. Single quotes
{ 'name': 'test' }
The error: Unexpected token ' in JSON at position 2. JSON strings and keys must
use double quotes, full stop. Fix: replace every ' used as a
string delimiter with " — but watch for apostrophes inside strings,
which are fine and must stay.
3. Unquoted keys
{ name: "test" }
The error: Unexpected token n / Expecting property name. Bare keys
are valid JavaScript, never valid JSON. Fix: quote the key:
"name".
4. Comments
{ "name": "test" } // set by deploy script
The error: Unexpected token /. JSON has no comment syntax by design.
Fix: delete them, or if you control the format, keep a conventional
"_comment" key instead. (Config formats that do allow comments — JSONC,
JSON5 — are different formats, and a strict parser will reject them.)
5. A missing comma or bracket
{ "a": 1 "b": 2 }
The error: Unexpected string in JSON at position 9. Every "unexpected string" /
"unexpected number" error is a separator problem: two values with no comma between them, or
an unclosed { or [ further up. Fix: add the comma
— or paste into the validator, which reports the line
where the parser gave up, and look just before that point.
Encoding gremlins
Some documents look perfectly valid and still refuse to parse. The invisible suspects:
-
A byte-order mark (BOM). Files saved as "UTF-8 with BOM" start with an
invisible U+FEFF character, producing
Unexpected token in JSON at position 0. An error at position 0 on a file that looks fine is almost always this. Fix: save as UTF-8 without BOM, or strip the first character. -
Smart quotes. Text pasted through Word, Google Docs, Slack or a CMS often
arrives with
“ ”instead of" ". They look right and parse wrong. Fix: retype the quotes, or turn off auto-formatting before copying. -
Real line breaks inside strings. JSON strings cannot contain literal
newlines — they must be escaped as
\n. Multi-line text pasted into a value fails withUnterminated string. -
Unescaped backslashes. Windows paths are the classic:
"path": "C:\temp\new"—\tand\nsilently become tab and newline, or fail outright on invalid escapes. Fix: double them:"C:\\temp\\new".
Numbers, dates and other quiet failures
These parse fine and still bite:
-
NaN,Infinityandundefinedare not JSON. Serializers handle them differently — JavaScript'sJSON.stringifyturnsNaNintonulland dropsundefinedobject values entirely, while Python's defaultjson.dumpshappily emitsNaN, producing JSON that other parsers reject. -
Big integers lose precision. JSON has no integer size limit, but
JavaScript parses numbers as 64-bit floats: anything above 9,007,199,254,740,991
(253 − 1) gets silently rounded. This is why the Twitter API ships
idandid_str. Fix: send large IDs as strings. -
There is no date type. Dates in JSON are strings by convention; use ISO
8601 (
"2026-07-04T09:00:00Z") and parse on arrival. Anything else —/Date(1234)/, locale-formatted strings — is a compatibility trap. -
Double-encoded JSON. If your "object" comes out of the parser as one long
string full of
\"escapes, it was stringified twice. Fix the producer; as a band-aid, parse twice.
Reading the error message
The position numbers are more useful than they look. Chrome and Node report a character
offset (at position 24 — count from 0); Firefox and Python report line and
column (line 1 column 25). Two habits make them useful: first, remember the
parser stops at the first place the document stops making sense, which is often just
after the real mistake — a missing comma on line 3 may be reported at line
4. Second, on minified one-line JSON, don't count characters by hand; paste it into the
JSON Validator and let it format the document and point
at the failing line.
Validate before you ship
Two closing habits save most of this debugging. Generate JSON with a serializer
(JSON.stringify, json.dumps), never by string concatenation —
hand-built JSON is where unescaped quotes and mismatched brackets come from. And validate at
the boundary: any JSON you accept from users, files or third-party APIs is untrusted input.
For log files and datasets where each line is its own JSON document, see the
JSONL converter — and if your JSON carries binary data,
read Base64 isn't encryption before you trust
what's inside it.