JSON

Fix "SyntaxError: Unexpected token in JSON" — All Causes

2026-05-03 · 8 min read · Validate JSON free →

The SyntaxError: Unexpected token X in JSON at position N message is the most common JSON error in JavaScript, Node.js, and browser applications. It means the JSON parser hit a character it did not expect at a specific position in the string. The frustrating part is that the position reported is often where the parser gave up — not where the actual mistake is. This guide covers every cause of this error with exact fixes.

How to Read the Error Message

The error format is: SyntaxError: Unexpected token [CHAR] in JSON at position [N]. The character tells you what the parser found. The position is the character index from the start of the string. Some environments (Node.js 20+, modern browsers) also give a line and column number which is more useful.

Token in errorMost likely cause
< at position 0Server returned HTML, not JSON (see below)
} or ]Trailing comma before this closing bracket
' (single quote)Used single quotes instead of double quotes
/ at position 0–3Comment in JSON (// not allowed)
u or nundefined or unquoted value
A letter at position 0Unquoted key or non-JSON preamble in response

Error 1: Server Returned HTML Instead of JSON

This is the #1 cause of Unexpected token < at position 0. Your fetch or XMLHttpRequest called an endpoint, but the server returned an HTML page instead of JSON. The < is the first character of <!DOCTYPE html> or an HTML error page. The JSON parser chokes immediately.

Causes: wrong URL (hitting a 404 page), server crash (500 error page returned), auth failure (redirect to a login page), or CORS error (browser received an HTML CORS rejection).

// WRONG — assumes response is always JSON
const data = await fetch('/api/users').then(r => r.json());

// RIGHT — check status and content type first
const res = await fetch('/api/users');
if (!res.ok) {
  const text = await res.text();
  throw new Error(`HTTP ${res.status}: ${text.slice(0, 200)}`);
}
const contentType = res.headers.get('content-type') || '';
if (!contentType.includes('application/json')) {
  throw new Error(`Expected JSON, got: ${contentType}`);
}
const data = await res.json();

Always read the raw response text when debugging this error. await res.text() shows you exactly what the server sent, not what you expected it to send.

Error 2: Trailing Comma

JSON does not allow a comma after the last item in an object or array. JavaScript does — which is exactly why developers write trailing commas by habit.

// BROKEN
{"name": "Maria", "role": "admin",}
["one", "two", "three",]

// FIXED
{"name": "Maria", "role": "admin"}
["one", "two", "three"]

The error points to the closing } or ], not the comma. Always check the character immediately before the closing bracket when you see this error.

Error 3: Single Quotes

JSON requires double quotes for all strings — both keys and values. Single quotes are valid JavaScript but invalid JSON. This is the most common error when copying JavaScript object literals into a JSON context.

// BROKEN
{'name': 'Maria', 'role': 'admin'}

// FIXED
{"name": "Maria", "role": "admin"}

Error 4: Unquoted Keys

In JavaScript object literals, keys can be unquoted if they are valid identifiers. JSON requires all keys to be double-quoted strings.

// BROKEN (valid JavaScript object, invalid JSON)
{name: "Maria", role: "admin"}

// FIXED
{"name": "Maria", "role": "admin"}

Error 5: Comments

JSON does not support comments — not // line comments, not /* */ block comments. This error appears most often in configuration files where developers naturally want to document their settings.

// BROKEN
{
  // User settings
  "theme": "dark",
  "language": "en" /* default */
}

// FIXED — remove comments, or use "_comment" key
{
  "_comment": "User settings",
  "theme": "dark",
  "language": "en"
}

If you need comments in your config files, switch to YAML, TOML, or JSONC (JSON with Comments — supported by VS Code).

Error 6: Undefined and Non-JSON Values

JSON has six types: string, number, boolean, null, object, array. undefined, NaN, Infinity, functions, and Date objects are not valid JSON values. If you stringify them and then parse, you get this error.

// This silently produces invalid JSON
JSON.stringify({a: undefined, b: NaN, c: Infinity});
// Result: "{}" — undefined and NaN/Infinity become nothing or null

// Safe pattern
const safe = {
  value: Number.isFinite(x) ? x : null,
  data: item ?? null   // undefined → null
};

Error 7: Parsing an Empty String

JSON.parse(""), JSON.parse(null), and JSON.parse(undefined) all throw this error. This happens when an API returns an empty body (like a 204 No Content) and you try to parse it.

// Guard against empty responses
function safeParse(text) {
  if (!text || !text.trim()) return null;
  try {
    return JSON.parse(text);
  } catch (err) {
    console.error('JSON parse error:', err.message, 'Input:', text.slice(0, 100));
    return null;
  }
}

Error 8: BOM or Invisible Characters

A Byte Order Mark (BOM) is an invisible character () sometimes added by Windows text editors at the start of a file. It makes JSON appear to start with an invisible character before the {, causing Unexpected token at position 0.

// Strip BOM before parsing
const jsonString = rawString.replace(/^/, '');
const data = JSON.parse(jsonString);

Error 9: Concatenated JSON Objects

Sometimes log files or streaming sources contain multiple JSON objects concatenated without any separator — this is called NDJSON (Newline Delimited JSON) or JSON Lines. JSON.parse cannot handle more than one root object.

// BROKEN — two JSON objects, not valid JSON
{"id":1,"name":"Maria"}{"id":2,"name":"Carlos"}

// FIXED — parse each line separately (NDJSON)
const objects = text
  .split('
')
  .filter(line => line.trim())
  .map(line => JSON.parse(line));

Debugging Strategy

When you hit this error: first, log the raw string before parsing — console.log(JSON.stringify(theString)) shows escape sequences and invisible characters. Second, paste the value into ToolPry's JSON Formatter, which shows the exact error location highlighted in the source. Third, check the error position and look at the character immediately before it — that is almost always where the real problem is, not the position itself.

Wrap all JSON.parse calls in try/catch in production code. A JSON parse error should never crash your application — it should be caught, logged with the raw input, and handled gracefully with a fallback.

Environment-Specific Error Messages

The exact wording of this error varies by environment, but they all mean the same thing:

Chrome/V8: SyntaxError: Unexpected token ',' in JSON at position 42 — newer versions give line and column numbers too.

Firefox/SpiderMonkey: SyntaxError: JSON.parse: unexpected character at line 3 column 18 of the JSON data — Firefox gives line and column numbers which are more useful than character position.

Node.js 18+: Multi-line error output with a visual pointer to the exact character. Node.js 20+ added significantly improved JSON parse error messages that show the surrounding context.

Python: json.decoder.JSONDecodeError: Expecting ',' delimiter: line 3 column 5 (char 42) — Python gives both line/column and character offset.

Java Jackson: com.fasterxml.jackson.core.JsonParseException: Unexpected character ('}' (code 125)): was expecting comma to separate Object entries — Jackson gives the exact character it found and what it expected instead, which is the most useful error message of any JSON library.

Prevention: Stop JSON Errors Before They Happen

Defensive coding eliminates most JSON errors before they reach your catch block. Use your language's official JSON serializer — never build JSON strings through string concatenation. JSON.stringify() in JavaScript, json.dumps() in Python, and their equivalents in every other language always produce valid JSON. String concatenation produces JSON that works until it encounters a value with a quote, backslash, or newline in it, at which point it silently produces invalid JSON.

Add JSON Schema validation at API boundaries. Tools like Ajv (JavaScript) and Pydantic (Python) validate incoming JSON against a schema before your business logic ever touches it, producing clear error messages at the point of entry rather than cryptic failures deep in your code.

Validate configuration files in CI. A JSON syntax error in a config file should fail the build, not the production deployment. Add python3 -m json.tool config.json > /dev/null as a build step — it exits with code 1 and prints the error if the JSON is invalid.

Frequently Asked Questions

Why does the error position point to the wrong place?

The position in a JSON parse error is where the parser gave up, not necessarily where the mistake is. A trailing comma causes the error to be reported at the closing bracket. A missing comma causes the error at the next key. A missing opening quote causes the error at the first character of the unquoted value. The actual mistake is typically one or two characters before the reported position. Always look backward from the error position to find the real issue.

How do I find a JSON error in a very large file?

Binary search works reliably: remove the second half of the file, try to parse the first half. If it parses successfully, the error is in the second half. If it fails, the error is in the first half. Repeat until you isolate the problem to a small section. For log files or generated JSON, check your generation code — a systematic error in a generator will produce the same mistake in every record, so check the first record and the last record. Paste the problematic section into ToolPry's JSON Formatter for an exact highlighted error location.

What causes JSON errors in production that do not appear in development?

The most common cause is user-generated content with special characters. A database field containing a double quote, backslash, or control character is fine in the database but causes a JSON error when you build a JSON string by concatenating the raw value without escaping it. Always use your language's JSON serializer, which handles escaping automatically. Other production-only causes include: encoding differences (UTF-8 vs Latin-1 databases), locale-specific number formatting (some locales use comma as decimal separator), and platform-specific line endings causing issues in multiline strings.

Can I auto-fix JSON errors programmatically?

For some error types, yes. The json-repair npm package and similar libraries attempt to fix common JSON errors automatically: trailing commas, single quotes, missing quotes around keys, and truncated JSON from incomplete API responses. These are useful for processing JSON from sources you do not control (scraped data, log files, user input) where you want to recover as much data as possible rather than failing completely. For APIs you control, fix the source rather than the symptoms.