CodeKitHub
English
Fix "Unexpected token" in JSON.parse: a field guide to every cause

Fix "Unexpected token" in JSON.parse: a field guide to every cause

Published Jul 23, 2026

SyntaxError: Unexpected token X in JSON at position N is one of the most common errors in JavaScript, and one of the least helpful — it tells you where the parser gave up, not why. Here’s how to actually fix it.

Step 1: read the position number

JSON.parse counts characters from the start of the string, starting at 0. If your JSON came from a variable, log the exact slice around that position before doing anything else:

try {
  JSON.parse(raw);
} catch (e) {
  const match = e.message.match(/position (\d+)/);
  if (match) {
    const pos = Number(match[1]);
    console.log(raw.slice(Math.max(0, pos - 20), pos + 20));
  }
}

That one snippet solves more of these errors than any advice about JSON syntax, because most “unexpected token” errors are really “I don’t know what my string actually contains” errors — trailing whitespace from a copy-paste, an extra newline from a template literal, or a byte-order-mark (BOM) at the very start (position 0, token , which is invisible in most editors).

The 7 causes, ranked by how often they actually happen

  1. Trailing comma. {"a": 1, "b": 2,} — valid in JS object literals, invalid in JSON. The comma before } or ] is the single most common cause.
  2. Single quotes instead of double quotes. {'a': 1} is JS, not JSON. JSON requires double quotes around both keys and string values, no exceptions.
  3. Unquoted keys. {a: 1} — again, valid JS, invalid JSON. Every key needs quotes.
  4. A JS value that isn’t valid JSON. undefined, NaN, a function, or a comment (// like this) — none of these exist in the JSON spec, only in JavaScript.
  5. Double-encoding. You called JSON.stringify() twice, or you’re parsing a string that’s already an object — check with typeof raw === 'string' before calling .parse().
  6. An empty string or undefined response. If a fetch failed silently or returned an empty body, JSON.parse("") throws Unexpected end of JSON input, a different but related error — check response.ok and log the raw body before parsing.
  7. BOM or invisible characters from copy-paste. Pasting JSON from a PDF, Word doc, or some terminal output can carry a BOM or non-breaking space that looks identical to a normal character.

The fastest fix: validate before you debug

Reading raw error messages character-by-character is slow. Paste the exact string into a formatter that highlights the invalid character directly instead of guessing from a position number — it turns “somewhere near character 812” into “this specific missing bracket, right here.” (Linked below.)

When the JSON is genuinely valid but still fails

If a formatter confirms your JSON is syntactically correct and JSON.parse still throws, the string you’re passing in isn’t the string you think it is. The most common reason: you’re calling .parse() on a Response object instead of its resolved body.

// Wrong — parses "[object Response]", not the body
const data = JSON.parse(await fetch(url));

// Right
const data = await (await fetch(url)).json();
// or, if you need the raw text first:
const text = await (await fetch(url)).text();
const data = JSON.parse(text);

Quick reference

Symptom Likely cause
Unexpected token } Trailing comma before the closing brace
Unexpected token ' Single quotes used instead of double quotes
Unexpected token a (or any letter) Unquoted object key
Unexpected end of JSON input Empty string, truncated response, or unclosed bracket
Unexpected token  (position 0) Byte-order-mark from a copy-pasted or Windows-saved file

None of these require memorizing anything — the fix is always the same three steps: log the slice around the reported position, run it through a formatter, fix the one character it flags.

← Back to Blog