JSON Parse Error: Unexpected Token — Every Cause, Explained
Fix "JSON parse error: unexpected token" fast — the real causes (trailing commas, single quotes, unquoted keys) with exact error text and fixes. Free JSON formatter, no sign-up.
Try it now: JSON Formatter & Validator — Format, validate and minify JSON in your browser. Pinpoints syntax errors by line and column, sorts keys for clean diffs, and never uploads your data.
What 'Unexpected Token' Actually Means
A JSON parser reads text one character at a time, grouping characters into tokens — {, }, a string, a number, a comma — and checking each new token against what JSON's grammar allows at that exact position in the document. A JSON parse error: unexpected tokenmeans the parser reached a character that isn't legal there, given everything it has already consumed. It is a json syntax error, not a schema or business-logic problem — the parser hasn't formed any opinion about whether a field is missing or a value is the wrong type, because the text never became data in the first place. Nothing downstream of JSON.parse ever runs.
That distinction matters because it tells you where to look. An unexpected token in json is always a problem with the raw text — a stray character, a missing quote, a copy-paste artifact from JavaScript source — never a problem with what the data means. Fix the text and the error disappears completely; there is no partial success, no "mostly parsed" state. Either the document is one of JSON's six value types, correctly formed, or the parser stops and throws at the first token that doesn't fit.
The Real Causes, One at a Time
In practice, almost every json.parse error traces back to one of five causes. Each one below shows the broken input, the exact message a parser throws for it, and the fix.
1. A trailing comma before } or ]
Legal in a JavaScript object or array literal, never legal in JSON. This is the single most common cause, because it's invisible when hand-editing a document — nothing about a trailing comma looks wrong to the eye.
{
"name": "Ada",
"roles": ["admin", "billing",]
}
→ SyntaxError: Unexpected token ] in JSON at position 50
(the comma before the closing bracket)
{
"name": "Ada",
}
→ SyntaxError: Unexpected token } in JSON
(no position number at all — V8's least helpful common case)Fix: delete the comma after the last property or the last array element. Note the second example — a trailing comma immediately before a closing brace is the one case V8 (Chrome, Node.js) reports with no position at all, which is exactly why re-scanning the text yourself, or using a tool that does it for you, beats reading the raw error message.
2. Single-quoted strings
JSON requires double quotes around every string and every key — no exceptions, and no fallback to single quotes the way JavaScript, Python, and most languages allow.
{"username":'Ada'}
→ SyntaxError: Unexpected token ' in JSON at position 12Fix: replace every ' with ". This one is common in code that builds a JSON string by hand with template literals or string concatenation, where single quotes are the natural default and it's easy to forget JSON doesn't share that leniency.
3. Unquoted object keys
Bare keys are valid in a JavaScript object literal — { status: "active" } runs fine as JS — but JSON requires every key to be a double-quoted string, with no bare-identifier shortcut.
{status: "active"}
→ SyntaxError: Unexpected token s in JSON at position 1
// Some newer engine versions phrase the same problem differently:
→ SyntaxError: Expected property name or '}' in JSON at position 1Fix: wrap every key in double quotes. This mistake almost always comes from pasting a JavaScript object literal — printed with console.log, copied out of source code, or typed from memory — straight into a field or tool that expects strict JSON.
4. A JavaScript value with no JSON equivalent
undefined, comments, and a trailing semicolon are all normal in JavaScript source and all nonexistent in JSON's grammar. They show up constantly when someone copies a const declaration out of a .js file instead of the JSON value itself.
{
"id": 1,
"name": "Ada",
"manager": undefined
}
→ SyntaxError: Unexpected token u in JSON at position 43{"a":1};
→ SyntaxError: Unexpected token ; in JSON at position 7
(newer engines: "Unexpected non-whitespace character after JSON at position 7")Fix: replace undefined with null or drop the key entirely, delete comments, and strip the trailing ; — none of the three exist in strict JSON, in any position.
5. Calling JSON.parse on something that isn't a JSON string
JSON.parse only accepts a string. Pass it anything else and it coerces the argument to a string first — which produces a message that looks confusing until you know what actually happened.
const data = { name: "Ada" };
JSON.parse(data);
// data.toString() → "[object Object]"
→ SyntaxError: Unexpected token o in JSON at position 1
(the parser saw "[object Object]" — [ then the letter o)const res = await fetch(url); const raw = await res.text(); // "" — an empty body JSON.parse(raw); → SyntaxError: Unexpected end of JSON input
Fix: don't call JSON.parseon a value that's already an object — it's redundant and, as shown above, actively wrong. For a fetch response, prefer res.json() directly, and guard against an empty body before parsing manually if the endpoint can legitimately return no content.
The Position Number Isn't a Line and Column
Every example above ends in "at position N." That number is a raw character offset counted from the very start of the string — including every newline, every space of indentation, every character inside every string that came before it. It is not a line number, and it is not a column. On a one-line minified payload the two happen to look similar; on any pretty-printed, multi-line document they diverge immediately, and scrolling to "character 43" by eye in a large file is not a realistic debugging step.
Converting a raw offset into a line and column is mechanical — count how many newline characters occur before that offset, and the column is the distance since the last one:
function locate(text, offset) {
const before = text.slice(0, offset);
const line = before.split("\n").length;
const column = offset - before.lastIndexOf("\n");
return { line, column };
}A tool that does this conversion for you turns "position 43" into "line 4, column 15" — a location you can actually click to or jump to, instead of a number you have to count out by hand.
Fixing It Without Guessing
GenKitLab's JSON Formatter runs your input through a real parser and, when it fails, converts the raw position into a line and column and points at the exact character — including the trailing-comma-before-a-brace case that some engines report with no position at all. It also formats, validates, minifies, and sorts keys, and it runs entirely in your browser: nothing you paste is uploaded anywhere, so pasting a real API response or a production payload to debug a parse error doesn't mean sending it to a server first.
If you're not yet sure whether what you're dealing with is a syntax break like the ones above, or data that parses fine but doesn't match the shape you expected, the Is My JSON Valid? guide walks through telling the two apart before you reach for the wrong tool. And for JSON's full grammar — every value type, every rule that's stricter than a JavaScript object literal, and the exact wording each engine uses for the same mistake — see the complete JSON Formatter guide.
Frequently asked questions
›What does "unexpected token" mean in a JSON parse error?
The parser reached a character that isn't legal at that position, given JSON's grammar and everything already read before it. It's a syntax-level failure, not a schema problem — the text never became data, so nothing about field names, types, or missing values is being evaluated yet.
›Why does JSON.parse throw "unexpected token" on JSON that looks fine?
It usually isn't actually valid JSON — it's valid-looking JavaScript. The most common causes are a trailing comma before } or ], single-quoted strings, unquoted object keys, or a JavaScript-only value like undefined copied in from source code. All four are legal JavaScript object literal syntax and all four are invalid JSON.
›What does the position number in a JSON.parse error actually mean?
It's a raw character offset counted from the very start of the string, including every newline and every space of indentation — not a line number or column. Converting it requires counting newline characters up to that offset; a formatter that reports line and column directly saves you doing that by hand.
›Why does JSON.parse fail with "unexpected end of JSON input"?
That specific message means the parser ran out of characters before the document was structurally complete — most often because the input is an empty string (a fetch response body that came back empty) or the payload got cut off mid-copy or mid-stream.
›Can I pass an already-parsed JavaScript object to JSON.parse?
No, and doing so produces a confusing error rather than an obviously wrong one. JSON.parse only accepts a string, so passing an object coerces it via toString() first — an object becomes the literal string "[object Object]", which then fails to parse as JSON with an unrelated-looking "unexpected token o" error.
›How do I find the exact line and column of a JSON syntax error?
Paste the document into a formatter that parses before displaying anything, like GenKitLab's JSON Formatter — it converts the raw character offset a parser reports into a line and column and points at the exact character, rather than leaving you to count offsets by hand.
Last updated