JSON

Unexpected Token in JSON: Fix <, u, ], and Position 0 Errors

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

Quickest fix: Paste your broken JSON into the ToolPry JSON Formatter — it detects the exact error type and offers one-click auto-repair. No signup, runs in your browser.
Error message token Likely cause Quick fix
< at position 0Server returned HTML (error page) instead of JSONCheck HTTP status code and endpoint URL
u at position 0Parsing the word undefined (not a string)Guard: if (str) JSON.parse(str)
] or }Trailing comma after last itemRemove comma before closing bracket
o at position 1Passed [object Object] instead of JSON stringUse JSON.stringify(obj) first
Single quote 'Single-quoted strings (valid JS, invalid JSON)Replace ' with "
End of JSON inputTruncated/empty responseCheck response body isn't empty (204, network cut)

You called fetch(), ran .json() on the response, and the console throws SyntaxError: Unexpected token < in JSON at position 0. The character in the message tells you what the parser found; the position tells you where it gave up — which is rarely where your mistake actually is. This guide maps every variant of this error to its real cause and the exact fix.

From building ToolPry's JSON Formatter: the most useful habit is to stop trusting the position number. For a trailing comma the parser reports the closing bracket; for a missing comma it reports the next key — almost always one token after the real problem. The formatter parses entirely in your browser (your payload is never uploaded) and surfaces the first structural violation, which is why it often lands a character or two before the native error. The rules it enforces come straight from RFC 8259, the JSON specification.

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();

Behaviour is identical across V8 (Chrome, Node.js) and SpiderMonkey (Firefox) — only the error wording differs, as covered below.

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"]

Tested: Node.js 22.x, Python 3.12.4, Chrome 125. Output may vary on older runtimes.

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"}

Tested: Node.js 22.x, Python 3.12.4, Chrome 125. Output may vary on older runtimes.

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"}

Tested: Node.js 22.x, Python 3.12.4, Chrome 125. Output may vary on older runtimes.

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"
}

Tested: Node.js 22.x, Python 3.12.4, Chrome 125. Output may vary on older runtimes.

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
};

Tested: Node.js 22.x, Python 3.12.4, Chrome 125. Output may vary on older runtimes.

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;
  }
}

Tested: Node.js 22.x, Python 3.12.4, Chrome 125. Output may vary on older runtimes.

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);

Tested: Node.js 22.x, Python 3.12.4, Chrome 125. Output may vary on older runtimes.

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));

Tested: Node.js 22.x, Python 3.12.4, Chrome 125. Output may vary on older runtimes.

Swagger UI: “is not valid JSON” Trailing Comma Error

Swagger UI throws SyntaxError: is not valid JSON when your OpenAPI spec file contains trailing commas. This is one of the most common sources of this error because developers edit swagger.json or inline API spec strings by hand, copying from JavaScript where trailing commas are legal.

// swagger.json — BROKEN (trailing comma after last path)
{
  "paths": {
    "/users": { "get": { "summary": "List users" } },
    "/orders": { "get": { "summary": "List orders" } },
  }
}

// FIXED — remove the comma after the last entry
{
  "paths": {
    "/users": { "get": { "summary": "List users" } },
    "/orders": { "get": { "summary": "List orders" } }
  }
}

Tested: Node.js 22.x, Python 3.12.4, Chrome 125. Output may vary on older runtimes.

The Swagger UI error message does not always tell you which line the trailing comma is on. Paste your spec into the ToolPry JSON Formatter — the auto-fix button strips all trailing commas in one click and shows you the clean spec you can copy back into Swagger.

If you are using Swagger UI via CDI or npm and loading the spec from a URL, the trailing comma may be in a shared config object passed to SwaggerUIBundle. Check that object definition in your JavaScript code for the same pattern.

MDN Reference: JSON.parse() and Unexpected Token Errors

The MDN documentation for JSON.parse() specifies that the method throws a SyntaxError when the string passed to it does not conform strictly to JSON syntax. The most important rule MDN highlights: JSON is not a superset of JavaScript. Specifically:

The error message text varies by JavaScript engine: V8 (Chrome/Node.js) says “Unexpected token , in JSON at position N”, while Firefox says “JSON.parse: unexpected character at line N column N”. The position number refers to the character offset in the original string, not the line number. The ToolPry JSON Formatter normalises this and shows you the exact line and column.

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.

See also: Common JSON Errors and How to Fix Them — the companion hub covering all 10 error types.

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.

JSON Parse Error FAQ

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.