JSON Parse Error: What It Means and How to Fix It Fast
JSON parse errors crash code in every language. This guide covers every common message — SyntaxError, JSONDecodeError, unexpected token — with exact fixes for JavaScript, Python, and TypeScript.
Have broken JSON right now? Fix it free in under 1 second — no signup.
Fix My JSON →A JSON parse error means your code tried to read a string as JSON and failed — the string doesn't follow the rules in RFC 8259, the spec that every JSON parser implements. This guide covers every common parse error message, the exact causes behind each one, and how to fix them in JavaScript, Python, and TypeScript.
What Is a JSON Parse Error?
When you call JSON.parse() in JavaScript or json.loads() in Python, the parser reads your string character by character and builds a data structure. The moment it finds something that violates the JSON spec — a stray comma, a single-quoted string, an unclosed bracket — it stops and throws an error.
The error doesn't mean the data is wrong in a business sense. It means the text you passed doesn't conform to JSON syntax. A number labelled "age" that says thirty instead of 30 will throw a parse error. So will a comma after the last item in an array.
JSON parse errors are extremely common in 2026 because so much JSON now comes from sources that aren't strict JSON emitters: LLM responses, Python scripts, copy-pasted API responses, and config files written by hand.
Common JSON Parse Error Messages
JavaScript: SyntaxError: Unexpected token
JSON.parse('{"name": "Alice",}')
// SyntaxError: Unexpected token } in JSON at position 18
"Unexpected token" means the parser found a character it didn't expect at that position. The position number points to where the parser got confused — look a few characters before it for the actual mistake. Common causes: trailing commas, single quotes, unquoted keys, or comments inside JSON.
JavaScript: SyntaxError: Unexpected end of JSON input
JSON.parse('{"name": "Alice"')
// SyntaxError: Unexpected end of JSON input
The JSON is truncated. An opening { or was never closed. Happens when streaming API responses are cut off, when you copy only part of a JSON blob, or when an LLM hits its token limit mid-response. See the dedicated guide on [how to fix unexpected end of JSON input for all causes and repair strategies.
Python: json.decoder.JSONDecodeError
import json
json.loads("{'name': 'Alice'}")
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
Python's JSONDecodeError is a subclass of ValueError and always includes the line, column, and character position. The message tells you exactly what the parser expected vs. what it found. This example fails because Python dict syntax uses single quotes, which aren't valid JSON.
Python: json.decoder.JSONDecodeError: Extra data
json.loads('{"a": 1} {"b": 2}')
json.decoder.JSONDecodeError: Extra data: line 1 column 9 (char 8)
Two valid JSON values concatenated without a separator. Common when merging API responses or when a script accidentally appends to a file that already contains JSON.
Node.js / TypeScript: Unexpected token < in JSON
const data = await response.json();
// SyntaxError: Unexpected token < in JSON at position 0
The token < means the server returned HTML instead of JSON — usually an error page (404, 500, or a login redirect). The response body starts with or . Always check response.ok before calling .json().
JSON Parse Error Causes by Source
1. LLM and AI Output (Most Common in 2026)
Language models produce malformed JSON more often than most developers expect. The model isn't "wrong" — it's generating text that looks like JSON but doesn't conform to the spec. Common LLM-specific failures:
- Markdown code fences: the model wraps JSON in
`json`blocks. The backticks andjsonlabel are markup, not data. - Python boolean literals: the model outputs
True,False,Noneinstead oftrue,false,null— because it was trained on Python code. - Trailing commas:
{"a": 1, "b": 2,}is valid Python, invalid JSON. - Truncated output: the model hits its max token limit mid-object.
- Explanatory text mixed in: the model adds a sentence before or after the JSON block.
# Typical raw LLM output — not valid JSON
"""
Here's the data:
json
{"name": "Alice", "active": True, "score": 95,}
"""
For structured output from LLMs in 2026, using response_format={"type": "json_object"} (OpenAI), tool_use (Anthropic), or response_mime_type="application/json" (Gemini) eliminates most of these issues at the source. When you can't control the model output, repair tools handle it downstream.
2. Python Dictionary Strings
Python's str() and repr() output Python syntax, not JSON:
data = {"name": "Alice", "active": True}
print(str(data))
{'name': 'Alice', 'active': True} ← Python syntax, NOT JSON
Two problems: single quotes and Python True. Passing this to json.loads() throws a JSONDecodeError. Always use json.dumps() to serialize Python data to JSON.
3. Truncated API Responses
If your HTTP client has a response size or timeout limit, the JSON may be cut off:
{"users": [{"id": 1, "name": "Alice"}, {"id": 2, "name":
The parser reports Unexpected end of JSON input. The fix is on the network side — increase your timeout, check for response size limits, or implement pagination.
4. HTML Instead of JSON
When a server returns an error page, redirect, or login wall, the content type changes from application/json to text/html. Your code tries to parse HTML as JSON and immediately fails on the < character.
// Always guard against non-JSON responses
const res = await fetch('/api/data');
if (!res.ok) throw new Error(HTTP ${res.status});
const data = await res.json();
5. Manual Editing and Config Files
Developers editing JSON config files by hand introduce two common errors: trailing commas (habits from JavaScript object literals) and comments (habits from YAML or TOML). Neither is valid JSON.
// INVALID — trailing comma
{
"port": 3000,
"debug": true,
}
// INVALID — comment
{
"port": 3000 // development port
}
If you need comments in config files, use JSONC (JSON with Comments) handled by a JSONC parser, or switch to TOML/YAML for human-edited config.
How to Fix JSON Parse Errors in Code
JavaScript / TypeScript
Always wrap JSON.parse() in a try/catch:
function safeParse<T>(input: string): T | null {
try {
return JSON.parse(input) as T;
} catch (e) {
console.error('JSON parse failed:', (e as SyntaxError).message);
return null;
}
}
For fetch responses, check the content type before parsing:
async function fetchJson<T>(url: string): Promise<T> {
const res = await fetch(url);
if (!res.ok) throw new Error(HTTP ${res.status}: ${res.statusText});
const contentType = res.headers.get('content-type') ?? '';
if (!contentType.includes('application/json')) {
throw new Error(Expected JSON, got: ${contentType});
}
return res.json() as Promise<T>;
}
Python
Catch json.JSONDecodeError specifically — it's a subclass of ValueError, so catching ValueError works too, but the specific class gives you line and column:
import json
def safe_parse(raw: str) -> dict | None:
try:
return json.loads(raw)
except json.JSONDecodeError as e:
print(f"Parse failed at line {e.lineno}, col {e.colno}: {e.msg}")
return None
For LLM output that may contain Python booleans or markdown fences, use the json-repair library:
from json_repair import repair_json
raw = "
json\n{\"name\": \"Alice\", \"active\": True}\n```"
fixed = repair_json(raw, return_objects=True)
{"name": "Alice", "active": true}
Install: pip install json-repair
Node.js — Streaming Responses
When parsing streaming LLM output, the JSON will be incomplete mid-stream. Buffer the full response before parsing:
javascript
let buffer = '';
for await (const chunk of stream) {
buffer += chunk;
}
const data = JSON.parse(buffer); // parse the complete response
Fix JSON Parse Errors Automatically
For one-off repairs — or when the JSON comes from an unreliable source with multiple overlapping issues — AI JSONMedic handles all of these automatically:
- Trailing commas in objects and arrays
- Single quotes on keys and values
- Python booleans (
True → true, False → false, None → null) - Markdown code fences from LLM output
- Truncated JSON with missing closing brackets
- Unquoted keys (
{name: "Alice"} → {"name": "Alice"}) - HTML in the input (returns an error rather than garbled data)
Paste your broken JSON → click Fix → get valid JSON back with a plain-English explanation of every change made. No account required, no data stored.
The JSON validator is useful when you only want to check validity without modifying the input — it reports the exact line and column of every error. The JSON formatter can then pretty-print the repaired output with consistent indentation.
For an explanation of every JSON term and rule, the JSON glossary covers the full spec in plain English.
Preventing JSON Parse Errors in LLM Pipelines (2026)
If your application consumes LLM output and you're frequently hitting parse errors, the cleanest fix is upstream:
OpenAI — json_object mode:python
response = client.chat.completions.create(
model="gpt-4o",
response_format={"type": "json_object"},
messages=[{"role": "user", "content": prompt}]
)
data = json.loads(response.choices[0].message.content)
OpenAI — structured_output with schema (100% guarantee):python
from pydantic import BaseModel
class UserData(BaseModel):
name: str
active: bool
score: int
response = client.beta.chat.completions.parse(
model="gpt-4o-2024-08-06",
messages=[{"role": "user", "content": prompt}],
response_format=UserData,
)
user = response.choices[0].message.parsed # already a UserData instance
Anthropic Claude — tool_use for structured output:python
response = client.messages.create(
model="claude-opus-4-7",
tools=[{
"name": "return_data",
"input_schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"active": {"type": "boolean"},
"score": {"type": "integer"}
},
"required": ["name", "active", "score"]
}
}],
tool_choice={"type": "tool", "name": "return_data"},
messages=[{"role": "user", "content": prompt}]
)
data = response.content[0].input # already a dict
Gemini — JSON MIME type:python
response = model.generate_content(
prompt,
generation_config={"response_mime_type": "application/json"}
)
data = json.loads(response.text)
When you can't use structured output (third-party integrations, older models), pair your LLM call with a repair step before parsing:
python
from json_repair import repair_json
raw = call_llm(prompt)
data = json.loads(repair_json(raw))
```
Quick Reference — Parse Errors by Message
| Error message | Language | Most likely cause | Quick fix |
|---|---|---|---|
Unexpected token } | JS | Trailing comma | Remove last comma |
Unexpected token ' | JS | Single-quoted string | Replace ' with " |
Unexpected end of JSON input | JS | Truncated JSON | Get full response |
Unexpected token < | JS | HTML response | Check HTTP status |
Expecting property name enclosed in double quotes | Python | Single-quoted keys | Use json.dumps() |
Extra data | Python | Two JSON objects concatenated | Parse first object only |
No JSON object could be decoded | Python | Empty or non-JSON input | Validate input first |
Frequently Asked Questions
What causesSyntaxError: Unexpected token u in JSON at position 0?
The value u at position 0 means the string passed to JSON.parse() is the JavaScript value undefined coerced to the string "undefined". This happens when response.body, localStorage.getItem(), or a function return value is undefined — not a JSON string. Check your variable before calling JSON.parse.
Most likely you're comparing a lenient parser (some libraries accept trailing commas or single quotes) with a strict one. JSON.parse() is strict per spec. If you need to share JSON between systems, always validate it against the strict spec first using AI JSONMedic's validator or python3 -m json.tool.
No. Standard JSON (RFC 8259) does not allow comments. If you pass // comment or / block / to any standard parser, you'll get a parse error. The JSONC and JSON5 formats extend JSON with comments, but require their own parsers — they're not interchangeable with standard JSON.
The error message always includes a position (JavaScript) or line/column (Python). Use the position to find the problem character: in a text editor, Ctrl+G (Go to line) with the line number, or count from the start of the string in JavaScript. In Python, e.lineno and e.colno give you exact coordinates. Alternatively, paste the JSON into AI JSONMedic and it will highlight and explain the error.
A parse error means the text isn't valid JSON at all — the syntax is broken. A schema validation error means the JSON is syntactically valid but doesn't match the expected structure (e.g., a required field is missing, or a value has the wrong type). Fix parse errors first, then validate structure with a schema validator. See the JSON Schema guide for schema validation examples.
Why doesJSON.parse(JSON.stringify(obj)) sometimes fail?
If obj contains non-serializable values — undefined, functions, Symbol, circular references, BigInt — JSON.stringify() either throws, returns undefined, or silently drops the value. Passing that result to JSON.parse() then fails or gives unexpected output. Inspect the value before stringifying: JSON.stringify(obj, null, 2) in the console shows what will actually be serialized.
Still dealing with broken JSON?
Paste it in and get it fixed in under 1 second — free, no signup, no install. Works with ChatGPT, Claude, n8n, and any AI output.
Fix My JSON Free →Related Articles