Common JSON Errors and How to Fix Them
Every parse failure you are likely to meet, what the message actually means, and why the reported line is often not the guilty one.
Read the Line Above the One Reported
Before the individual errors, one principle that resolves most of them faster than any lookup table. A parser reads left to right and complains at the first point where the input becomes grammatically impossible — which is frequently after the character you got wrong.
{
"name": "Jane" ← the mistake is here (missing comma)
"age": 25 ← the error is reported here
}After reading "Jane" the parser is content: a value may legally be followed by a comma or a closing brace. Only on the next line, finding a string where one of those two was required, does it fail. So it names line 3 — a line that is entirely correct.
The same logic explains trailing-comma errors landing on the closing brace. When a JSON error names a line, look at the line before it first.
Trailing Commas
{
"name": "Jane",
"roles": ["admin", "editor"],
}Message: Unexpected token } in JSON · Python: Expecting property name enclosed in double quotes
Remove the comma after the last element. This is the single most common JSON error, because trailing commas are valid in JavaScript object literals, in Python dicts, in JSON5 and in the JSONC files VS Code uses for its own settings. Every day you write code where this is fine, and then JSON rejects it.
Single Quotes
{ 'name': 'Jane' } // invalid
{ "name": "Jane" } // validMessage: Unexpected token ' in JSON at position 2
JSON permits double quotes only, for both keys and string values. There is no configuration that relaxes this. Seeing single quotes usually means the text came from a Python print() of a dict, or from a JavaScript object literal, rather than from a real serialiser. Re-generate it with json.dumps() or JSON.stringify() instead of hand-editing.
Unquoted Keys
{ name: "Jane" } // valid JavaScript, invalid JSON
{ "name": "Jane" } // valid JSONEvery key must be a quoted string. JavaScript allows bare identifiers as keys and JSON does not — another case where the surrounding language's habits leak into a stricter format.
Unescaped Characters Inside Strings
{ "quote": "She said "hello" to me" } // invalid
{ "quote": "She said \"hello\" to me" } // valid
{ "path": "C:\Users\Alice" } // invalid
{ "path": "C:\\Users\\Alice" } // valid
{ "note": "line one
line two" } // invalid — literal newline
{ "note": "line one\nline two" } // validThree separate rules here. A double quote inside a string must be escaped, or it terminates the string early. A backslash is itself the escape character, so a literal backslash must be doubled — Windows paths hit this constantly. And control characters, including literal newlines and tabs, cannot appear raw inside a string; they must be written as \n and \t. The escaping guide covers the full set.
Unexpected End of JSON Input
Message: Unexpected end of JSON input · Python: Expecting value: line 1 column 1 (char 0)
The parser reached the end of the text while still expecting something. Three common causes:
- An empty string. An empty document is not valid JSON — the grammar requires exactly one top-level value. Check for empty input before parsing.
- A truncated response. A connection dropped, a timeout fired, or a write was cut short mid-document. Compare the payload length against the
Content-Lengthheader. - An unclosed bracket, brace or string. A missing
}at the end of a large file produces exactly this. A formatter makes it obvious, because the indentation never returns to the left margin.
Unexpected Token < — You Are Parsing HTML
<!DOCTYPE html>
<html><head><title>404 Not Found</title></head>Message: Unexpected token < in JSON at position 0
This is the most frequent "JSON error" in web development and it is not a JSON error at all. Your request returned an HTML page — a 404, a 500, a login redirect, or a proxy error — and the parser was handed that instead. Nothing in your JSON handling is broken.
Check the response status and content type before parsing. In fetch, note that a 404 or 500 does not cause a rejection; you have to test response.ok yourself:
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status} ${response.statusText}`);
}
const data = await response.json();In PHP, the same symptom appears when a warning or notice is emitted before your JSON output, prepending HTML to an otherwise valid body. See the PHP guide.
Invalid Values
{ "value": undefined } // invalid — no undefined in JSON
{ "value": NaN } // invalid
{ "value": Infinity } // invalid
{ "count": 01 } // invalid — no leading zeros
{ "price": .5 } // invalid — needs a leading digit: 0.5
{ "price": 1. } // invalid — needs a trailing digit: 1.0
{ "hex": 0xFF } // invalid — no hexadecimal literalsJSON has exactly seven value types and a deliberately narrow number format. NaN and Infinity are the interesting omissions: JSON.stringify silently converts them to null rather than failing, so a division by zero somewhere upstream turns into a mysterious null downstream with no error anywhere. undefined behaves differently again — object properties holding it are dropped entirely, while array elements become null.
Comments
{
// this breaks the document
"name": "Jane"
}JSON has no comment syntax — neither // nor /* */. This was an intentional decision by JSON's designer, who found that comments were being used to carry parsing directives and undermined interoperability.
The confusion is understandable, because several things that look like JSON do allow comments: tsconfig.json and VS Code's settings are JSONC, and JSON5 permits them too. If you need annotated configuration, use one of those formats deliberately — or add a "_comment" key, which is a legitimate string value and a common workaround.
Invisible Characters
When JSON looks unimpeachable and still will not parse, the problem is usually something you cannot see:
- A byte-order mark. Files saved as "UTF-8 with BOM" begin with three invisible bytes. Many parsers reject them at position 0. Re-save as UTF-8 without BOM.
- Smart quotes. Text pasted from Word, Google Docs or a chat client may contain
“and”rather than". They look almost identical and are not valid delimiters. - Non-breaking spaces. Copied from a web page,
U+00A0renders like a normal space but is not whitespace as far as the grammar is concerned.
The quickest diagnosis is to retype the suspect line by hand. If a retyped copy parses and the original does not, you have found your invisible character.
Repairing Them Automatically
Most of the errors above are mechanical, and the parser on this site can undo them for you. Paste a document that fails to parse and a Fix Common Errors action appears alongside the error message. It handles:
- Line and block comments, removed
- Single-quoted strings, converted to double quotes
- Smart quotes used as delimiters, normalised
- Bare identifier keys, quoted
- Trailing commas, dropped
- Raw newlines and tabs inside strings, escaped
Two deliberate limits. It never modifies a document that already parses — a URL containing // or a colon inside a string value is content, not a syntax error, and is left exactly as it is. And if the repair does not produce valid JSON, your original text is kept rather than replaced with a differently broken version.
Everything runs in your browser, so a document you are repairing is never uploaded. Treat the result as a starting point rather than an answer: read the diff before pasting it back into anything that matters.
Frequently Asked Questions
Why does the JSON error point to the wrong line?
A parser reports the first position where the grammar became impossible, which is usually one token after your actual mistake. A missing comma is only detectable when the next key appears, so the error lands there. As a rule, check the line above the one reported.
What does 'Unexpected token < in JSON at position 0' mean?
Your code received HTML, not JSON — almost always a server error page, a 404, or a login redirect. Nothing is wrong with your JSON handling. Check the HTTP status code and the Content-Type header of the response instead.
Why is my valid-looking JSON rejected?
The usual culprits are invisible: a byte-order mark at the start of the file, a smart quote pasted from a word processor, or a non-breaking space that looks identical to a normal one. Viewing the raw bytes or re-typing the suspect line usually reveals it.
Can trailing commas ever be valid in JSON?
Not in standard JSON, as defined by RFC 8259. They are valid in JavaScript object literals, in JSON5, and in JSONC — the variant VS Code uses for its config files — which is exactly why the mistake is so easy to make.