What “invalid JSON” actually means
JSON is a deliberately small, strict format. A parser reads the whole document or rejects all of it — there is no partial success and no tolerant mode. So a single stray character thousands of lines in makes the entire file unusable, which is why the position in the error message matters as much as the message itself.
Validating here means checking that the document parses. That is a different question from whether it contains what your application expects, which is covered further down.
The eight things that actually break JSON
In practice almost every parse failure is one of these. The first four are all cases of JavaScript being more forgiving than JSON.
1. A trailing comma
The most common one by a wide margin. JSON allows no comma after the final item.
{ "a": 1, "b": 2, } invalid
{ "a": 1, "b": 2 } valid2. Single quotes
JSON strings and keys use double quotes only. Single quotes are a JavaScript habit.
{ 'name': 'Ada' } invalid
{ "name": "Ada" } valid3. Unquoted keys
Every key is a quoted string, even when it looks like a plain identifier.
{ name: "Ada" } invalid
{ "name": "Ada" } valid4. Comments
JSON has no comments of any kind. Both // and /* */ are rejected. This surprises people whose editor accepts them — see the note on JSONC below.
5. Unescaped characters inside a string
A literal newline, tab or double quote cannot appear raw inside a JSON string; it has to be escaped. This is the one that bites when a value was built by concatenating text.
{ "note": "line one
line two" } invalid
{ "note": "line one\nline two" } valid6. A missing or mismatched bracket
Usually reported at the very end of the file rather than where the problem is, because the parser only discovers the imbalance when it runs out of input. If the error points at the last character, suspect this.
7. Values JSON does not have
NaN, Infinity, -Infinity and undefined are all valid in JavaScript and none of them are valid JSON. There is no date type either — dates are strings by convention, usually ISO 8601.
8. Something after the end
A JSON document holds exactly one top-level value. Two objects one after another, or a stray character after the closing brace, is invalid — this is what trips people up when they concatenate API responses or paste twice by accident.
How to read the error
Browser parsers report the character offset where parsing stopped, not where the mistake was made. Those are frequently different places, and knowing which is which saves most of the search time:
- Unexpected token — a character appeared where the grammar did not allow one. The real fault is usually just before the reported position: a missing comma, or a comma too many.
- Unexpected end of JSON input — the document stopped mid-structure. A bracket or brace was never closed, or the file was truncated in transit.
- Unexpected non-whitespace character after JSON — item 8 above. The document was complete and then continued.
If the position looks like it points at perfectly good text, run the document through a formatter first. Reindenting turns a one-line file into a structure your eye can follow, and the imbalance usually becomes obvious.
Parsing cleanly is not the same as being correct
A document can be flawless JSON and still be wrong for your purpose. Three cases worth knowing, none of which any syntax validator reports:
- Missing or mistyped fields. Checking that
emailexists and is a string, or thatageis a number in a range, is JSON Schema validation — a separate job from parsing, and not what this tool does. - Duplicate keys. The specification permits them. The document parses and one value silently wins — but which one is not guaranteed to be the same across languages, so the same file can behave differently in two services.
- Large numbers. JSON numbers have no size limit, but most parsers read them as 64-bit floats. An integer beyond roughly 9×1015 — a Twitter-style ID, say — parses without complaint and comes back subtly wrong. Transport those as strings.
JSON, JSONC and JSON5
If a file with comments works in your editor but fails here, it is probably not JSON. tsconfig.json, devcontainer.json and VS Code’s settings are JSONC — JSON with comments and trailing commas — and JSON5 goes further, allowing unquoted keys and single quotes. Both are real formats with real tooling. Neither is accepted by a standard JSON parser, so a file that is fine in one place can be rejected by the next service that reads it. Validating against strict JSON is how you find that out before it ships.