How to Fix Broken JSON Without Understanding the Error — Practical Guide
Sometimes you receive malformed JSON from an API, legacy system, or AI-generated output and need to fix it fast — even if you do not understand why it is broken. This guide gives you practical tools and patterns to fix common JSON errors automatically, from quick one-liners to fully automated repair pipelines, with exact error messages mapped to exact fixes.
jsonrepair
npm package that fixes most JSON automatically
jq
command-line tool to validate and reformat JSON
Python
json module gives precise error location
95%+
of common JSON errors fixed automatically by jsonrepair
Quick Fix — Use jsonrepair Library (Node.js)
The jsonrepair npm package fixes over 95% of common JSON issues automatically without any configuration. Install it once and call it on any broken JSON string:
# Install once
npm install jsonrepair
# Or use globally from CLI
npm install -g jsonrepairimport { jsonrepair } from 'jsonrepair';
// Fix trailing commas (most common issue)
jsonrepair('{"name":"Alice","age":30,}')
// → '{"name":"Alice","age":30}'
// Fix single quotes → double quotes
jsonrepair("{'name':'Alice'}")
// → '{"name":"Alice"}'
// Fix unquoted keys
jsonrepair('{name:"Alice",age:30}')
// → '{"name":"Alice","age":30}'
// Fix missing quotes on string values
jsonrepair('{"status":active}')
// → '{"status":"active"}'
// Fix concatenated JSON objects (wraps in array)
jsonrepair('{"a":1}{"b":2}')
// → '[{"a":1},{"b":2}]'
// Fix truncated/incomplete JSON (adds missing brackets)
jsonrepair('{"name":"Alice","items":["a","b"')
// → '{"name":"Alice","items":["a","b"]}'
// Fix Python-style literals
jsonrepair('{"active": True, "data": None, "missing": NaN}')
// → '{"active": true, "data": null, "missing": null}'
// Fix comments (strips them)
jsonrepair('{"name": "Alice" /* primary user */}')
// → '{"name": "Alice"}'# Repair a JSON file and save the output
npx jsonrepair broken.json > fixed.json
# Pipe from stdin
cat broken.json | npx jsonrepair > fixed.json
# Use in a Node.js script
node -e "
const {jsonrepair} = require('jsonrepair');
const fs = require('fs');
const broken = fs.readFileSync('broken.json', 'utf8');
fs.writeFileSync('fixed.json', jsonrepair(broken));
console.log('Repaired successfully');
"Using Python to Find the Exact Error Location
Python's built-in JSON module gives you the exact line and column of the error, which is invaluable for debugging large JSON files where you cannot eyeball the problem:
import json
broken_json = '''
{
"name": "Alice",
"age": 30,
"tags": ["admin", "user",],
"active": True
}
'''
try:
data = json.loads(broken_json)
print("Valid JSON:", data)
except json.JSONDecodeError as e:
print(f"Error: {e.msg}")
print(f"Line: {e.lineno}, Column: {e.colno}")
print(f"At character position: {e.pos}")
# Show the problematic line with a visual pointer
lines = broken_json.split('\n')
if e.lineno <= len(lines):
line = lines[e.lineno - 1]
print(f"Problem line: {line!r}")
print(" " * (e.colno - 1) + "^--- error here")
# Output:
# Error: Expecting property name enclosed in double quotes
# Line: 5, Column: 29
# Problem line: ' "tags": ["admin", "user",],'
# ^--- error herePython Error Messages Decoded
"Expecting property name enclosed in double quotes" means trailing comma before closing brace or bracket. "Unexpected end of JSON input" means the JSON is truncated. "Expecting value" means a key exists but the value is missing or invalid. "Extra data" means multiple JSON objects were concatenated without an array wrapper.
The 5 Most Common JSON Mistakes and Their Fixes
Invalid JSON (5 common issues)
// 1. Trailing commas (most common — not allowed in JSON spec)
{"name": "Alice", "age": 30,}
["a", "b", "c",]
// 2. Single quotes instead of double quotes
{'name': 'Alice', 'active': 'true'}
// 3. Unquoted property keys (valid JavaScript, not valid JSON)
{name: "Alice", age: 30}
// 4. Python/JavaScript runtime literals instead of JSON values
{"active": True, "data": None, "count": NaN, "big": Infinity}
// 5. Comments (JSON spec explicitly forbids them)
{
// This is the user object
"name": "Alice" /* primary user */
}Valid JSON (corrected)
// 1. Remove trailing commas
{"name": "Alice", "age": 30}
["a", "b", "c"]
// 2. Use double quotes everywhere
{"name": "Alice", "active": "true"}
// 3. Quote all property keys
{"name": "Alice", "age": 30}
// 4. Use JSON-compliant values only
{"active": true, "data": null, "count": 0, "big": 1e308}
// 5. No comments allowed — use a _comment field if needed
{
"_comment": "This is the user object",
"name": "Alice"
}Error Message to Fix Cheat Sheet
| Item | Error Message You See | What It Means and How to Fix |
|---|---|---|
| Unexpected token , in JSON | Trailing comma before ] or } | Search for ,] or ,} and remove the comma |
| Unexpected token ' in JSON | Single quotes used instead of double | Replace all single quotes with double quotes |
| Unexpected token T in JSON | Python True used instead of JSON true | Replace True→true, False→false, None→null |
| Unexpected end of JSON input | JSON is truncated — missing closing brackets | Count opening vs closing braces and brackets — add missing ones |
| Unexpected token at position 0 | BOM character or whitespace before opening { | Strip BOM: text.replace(/^\uFEFF/, "") |
| Extra data after JSON value | Multiple JSON objects concatenated | Wrap in [ ] to make a JSON array, or split and parse separately |
| Property name must be a string | Unquoted key — JavaScript object syntax | Add double quotes around every property name |
Command Line Validation with jq
# Install jq
brew install jq # macOS
apt-get install jq # Ubuntu/Debian
choco install jq # Windows (Chocolatey)
# Validate and pretty-print (shows error with line number if invalid)
echo '{"name":"Alice","age":30}' | jq .
# Validate a file
cat data.json | jq .
# Validate without output (exit code 0=valid, 1=invalid)
cat data.json | jq . > /dev/null && echo "Valid" || echo "Invalid"
# Find error in large file
cat data.json | jq . 2>&1 | grep "parse error"
# Extract specific field to verify parsing
cat data.json | jq '.users[0].name'
# Compact output (minify valid JSON)
cat data.json | jq -c .
# Sort keys alphabetically (useful for diffing JSON files)
cat data.json | jq -S .Automated Repair Pipeline for Batch Processing
For processing batches of potentially-broken JSON from external sources (APIs, scrapers, user uploads), use this complete repair pipeline with progressive fallback:
import json
import re
import subprocess
from typing import Optional
def try_parse(text: str) -> Optional[dict]:
"""Try to parse JSON. Returns None if it fails."""
try:
return json.loads(text)
except json.JSONDecodeError:
return None
def fix_python_literals(text: str) -> str:
"""Replace Python-style literals with JSON equivalents."""
text = text.replace('True', 'true')
text = text.replace('False', 'false')
text = text.replace('None', 'null')
text = re.sub(r'\bNaN\b', 'null', text)
text = re.sub(r'\bInfinity\b', '1e308', text)
return text
def strip_comments(text: str) -> str:
"""Remove JavaScript-style comments from JSON."""
text = re.sub(r'//.*?$', '', text, flags=re.MULTILINE)
text = re.sub(r'/\*.*?\*/', '', text, flags=re.DOTALL)
return text
def fix_trailing_commas(text: str) -> str:
"""Remove trailing commas before } and ]."""
return re.sub(r',\s*([}\]])', r'\1', text)
def repair_with_jsonrepair(text: str) -> str:
"""Use jsonrepair npm package as final fallback."""
try:
result = subprocess.run(
['npx', 'jsonrepair'],
input=text, capture_output=True, text=True, timeout=10
)
if result.returncode == 0:
return result.stdout
except (subprocess.TimeoutExpired, FileNotFoundError):
pass
return text
def process_json(raw: str) -> dict:
"""Parse JSON with progressive repair strategy."""
# Step 1: Parse as-is (fastest path)
if result := try_parse(raw):
return result
# Step 2: Strip BOM
cleaned = raw.lstrip('\ufeff')
if result := try_parse(cleaned):
return result
# Step 3: Fix Python literals
cleaned = fix_python_literals(cleaned)
if result := try_parse(cleaned):
return result
# Step 4: Strip comments
cleaned = strip_comments(cleaned)
if result := try_parse(cleaned):
return result
# Step 5: Fix trailing commas
cleaned = fix_trailing_commas(cleaned)
if result := try_parse(cleaned):
return result
# Step 6: Nuclear option — use jsonrepair
repaired = repair_with_jsonrepair(raw)
if result := try_parse(repaired):
return result
# Nothing worked — raise with diagnostics
try:
json.loads(raw)
except json.JSONDecodeError as e:
raise ValueError(
f"Could not repair JSON. Error at line {e.lineno}, col {e.colno}: {e.msg}"
) from e
# Usage:
broken = '{"name": "Alice", active: True, tags: ["admin",],}'
data = process_json(broken)
print(data) # {'name': 'Alice', 'active': True, 'tags': ['admin']}TypeScript Repair Utility
/**
* Try to parse JSON, repairing common issues automatically.
* Falls back through repair steps before throwing.
*/
export async function parseJsonSafely<T = unknown>(input: string): Promise<T> {
// Step 1: Try as-is
try { return JSON.parse(input) as T; } catch {}
// Step 2: Strip BOM and leading whitespace
let cleaned = input.replace(/^/, '').trim();
// Step 3: Fix Python literals
cleaned = cleaned
.replace(/\bTrue\b/g, 'true')
.replace(/\bFalse\b/g, 'false')
.replace(/\bNone\b/g, 'null')
.replace(/\bNaN\b/g, 'null');
// Step 4: Remove trailing commas before } or ]
cleaned = cleaned.replace(/,\s*([}\]])/g, '$1');
// Step 5: Try repaired version
try { return JSON.parse(cleaned) as T; } catch {}
// Step 6: Use jsonrepair
const { jsonrepair } = await import('jsonrepair');
try {
return JSON.parse(jsonrepair(input)) as T;
} catch (e) {
throw new Error(`Failed to parse JSON after all repair attempts: ${String(e)}`);
}
}
// Usage:
const data = await parseJsonSafely<{ name: string }>('{"name": "Alice",}');
console.log(data.name); // AliceIdentifying Specific Error Types at a Glance
"Unexpected token" errors
Usually means: wrong quote type (single vs double), unquoted key, or illegal character. Look at the character at the reported position — it will be the culprit. The error message often includes the unexpected character in quotes.
"Unexpected end of JSON input"
The JSON is cut off or incomplete. Common when API responses are streamed or truncated by a length limit. Count the opening and closing brace and bracket pairs — one set is missing its closing half.
"Expected , or }" errors
A comma is missing between properties, or the previous value did not close properly. Walk backwards from the error position to find where the structure broke.
"Circular structure to JSON"
This happens at JSON.stringify time. Your JavaScript object has circular references (object A references B which references A). Use a replacer function or the flatted package to handle circular structures.
Encoding issues (BOM, null bytes)
UTF-8 BOM character at the start of a file, null bytes, or non-UTF8 sequences can break parsing. Strip with: text.replace(/^\uFEFF/, "").replace(/\u0000/g, "").
JSON.stringify returns undefined
This happens when you pass undefined itself, a function, or a Symbol to JSON.stringify. These types are not serializable. Use JSON.stringify(value) ?? "null" as a safe fallback.
Preventing Broken JSON in Your Own Code
Never build JSON by hand with string concatenation
Use JSON.stringify() in JavaScript, json.dumps() in Python, or your language equivalent. String concatenation is the top source of malformed JSON in homegrown code — one unescaped quote breaks everything.
Validate at API boundaries
When receiving JSON from external APIs, wrap the parse in try/catch and log the raw response on failure. This makes debugging 10x easier than a cryptic downstream error with no context.
Use Zod or similar for structure validation
JSON.parse only validates syntax, not structure. Libraries like Zod let you define a schema and validate the parsed object — catching wrong types and missing required fields that JSON.parse misses.
Handle partial responses from streaming APIs
When consuming streaming JSON (SSE, chunked HTTP), buffer the incoming data and only parse when you have a complete object. Streaming APIs frequently send partial JSON that is invalid until the full chunk arrives.
Test with edge case inputs
Include empty object {}, empty array [], null values, nested structures, and unicode strings in your test suite for any JSON parsing code. These are where most JSON handling bugs hide.
Use an online JSON tool for quick fixes