“Unexpected token” means the JSON parser met a character that cannot legally appear at that position — and stopped. The fix is always the same two steps: find the exact position, then recognize which of a handful of classic mistakes put the illegal character there. Paste the document into the JSON Formatter & Validator and it reports the first error with its precise line and column, highlighting the line in the gutter.
Read the error message first
Browser messages look like Unexpected token } in JSON at position 251 — position counts characters from the start, which is useless in a minified single-line document. A validator that translates position into line and column (and shows you the line) turns a hunt into a glance. Note that the parser stops at the first violation: fix it, re-validate, and repeat if needed.
The five mistakes behind almost every case
- Trailing commas.
{"a": 1, "b": 2,}— legal in JavaScript, illegal in JSON. Reported as an unexpected}or]. - Single quotes.
{'name': 'Ada'}— JSON strings and keys must use double quotes. Reported as an unexpected'at the first quote. - Unquoted keys.
{name: "Ada"}— object keys are strings and need quotes, unlike JavaScript object literals. - Comments.
// config for prod— no comment syntax exists in JSON. The/is the unexpected token. - Raw line breaks or control characters inside strings. A pasted value with a real newline in it must be escaped as
\n. Copy-pasting from terminals also smuggles in invisible characters — smart quotes from chat apps are a classic.
Invisible characters: the BOM and its friends
Sometimes the input looks perfect and still fails at position 0 with a baffling Unexpected token in JSON at position 0 — note the seemingly empty quotes. The culprit is usually a byte order mark: Windows editors and PowerShell's Out-File like to prepend U+FEFF to UTF-8 files, and RFC 8259 forbids it at the start of a JSON text. The same family of bugs comes from non-breaking spaces (U+00A0) pasted from web pages and “smart quotes” (“ ”) substituted by chat apps and word processors — visually near-identical to legal characters, lexically illegal. Fix: re-save as “UTF-8 without BOM”, or strip the first character in code with text.replace(/^\uFEFF/, ""); for smart quotes, retype the quotes in a code editor. A validator that points at position 0 or at a quote that looks fine is practically shouting “invisible character”.
Values JavaScript allows but JSON doesn't
NaN, Infinity and undefined are legal JavaScript values with no JSON representation — RFC 8259 numbers are finite, and there is no undefined. Hand-built strings containing them fail with Unexpected token N (from NaN) or Unexpected token I. Note the asymmetry: JSON.stringify(NaN) quietly emits null rather than throwing, so these tokens in a document almost always mean someone concatenated strings instead of serializing. The same goes for 0x1F hex literals and numbers like .5 or +1 — JSON requires 0.5 and 1.
When the JSON is not the problem
Unexpected token < in JSON at position 0 deserves its own mention: the < is the first character of <html>. Your code parsed an HTML error page, a 404, or a login redirect as if it were an API response. The JSON was never malformed — there was no JSON. Log response.text() before parsing, and check the status code and content-type first.
A worked example
{
"name": "deploy",
"retries": 3,
"env": "prod",
}A validator reports something like Unexpected token } at line 5, column 1. The real mistake is the comma at the end of line 4 — the parser only discovered it when the closing brace arrived where a new key was required. Delete the comma and the document is valid. This one-line-off pattern is why the rule of thumb is: look at the reported position, then one token back.
Prevent it next time
Generate JSON with a serializer (JSON.stringify, json.dumps) instead of string concatenation or hand-editing; serializers cannot produce syntax errors. When hand-editing is unavoidable — config files, fixtures — validate before committing, and diff edited configs with the Text Diff tool to see exactly what changed when something breaks.
