Fix Invalid JSON From LLMs: Truncation, Commas, Quotes
Fix invalid JSON from LLMs: truncated output, trailing commas, single quotes and code fences. How to repair it, when to use structured outputs, and a free tool.
To fix invalid JSON from an LLM, first check whether the response was truncated, then extract the JSON from any code fence or prose, try JSON.parse, and fall back to a repair library such as jsonrepair for trailing commas, single quotes and comments. Validate the result against a schema. To paste and fix one response by hand, use the free JSON Repair tool.
Why do LLMs return invalid JSON?
Language models generate text one token at a time. They have seen a lot of JSON in training, but also a lot of JavaScript object literals, Python dicts and Markdown. Unless decoding is constrained to a grammar, the model can drift into any of those. Strict JSON, as defined in RFC 8259, has no comments, no trailing commas, no single quotes, and must be UTF-8 when exchanged between systems. A model that is "almost right" still breaks JSON.parse.
The failures fall into a small number of patterns. Most are cosmetic: the data is all there, just in the wrong syntax. One is not cosmetic at all.
| Failure | Typical cause | Safe to auto-repair? |
|---|---|---|
| Markdown code fence around the JSON | Chat-style formatting habits | Yes |
| Prose before or after ("Sure! Here is...") | Model is being helpful | Yes, but extract first |
| Trailing commas | JavaScript and Python habits | Yes |
Single quotes, True, None | Python dict syntax | Yes |
| Comments, unquoted keys | JSON5 or JavaScript syntax | Yes |
| Raw newlines inside strings, smart quotes | Long text fields, copy-paste | Yes |
| Output stops mid-object | Hit max_tokens | No: data is missing |
What does jsonrepair actually fix?
jsonrepair is a widely used JavaScript library for this job. It had 15,602,785 npm downloads between August 31 and September 29, 2026 (npm downloads API), and it is what the site's JSON Repair tool runs. Each case below was run through jsonrepair 3.15.0. The left column fails JSON.parse; the right column is the exact repaired output.
// Trailing commas
{"ids": [1, 2, 3,], "ok": true,}
→ {"ids": [1, 2, 3], "ok": true}
// Python literals and single quotes
{'name': 'Ada', 'active': True, 'manager': None}
→ {"name": "Ada", "active": true, "manager": null}
// Unquoted keys and a missing comma
{name: "Ada", tags: ["a" "b"]}
→ {"name": "Ada", "tags": ["a", "b"]}
// Smart quotes
{“name”: “Ada”}
→ {"name": "Ada"}
// Raw newline inside a string (JSON.parse: "Bad control character")
{"bio": "line one
line two"}
→ {"bio": "line one\nline two"}
// Code fence
```json
{"name": "Ada", "role": "admin"}
```
→ {"name": "Ada", "role": "admin"}
// Two objects on separate lines
{"a":1}
{"a":2}
→ [{"a":1}, {"a":2}]Comments are removed too, though the whitespace they occupied stays behind, which is harmless. For pasting a single broken response, the JSON Repair tool does all of this in the browser, with nothing uploaded.
When does JSON repair make things worse?
A repair library guarantees valid syntax, not correct data. Three cases from the same test run show where it goes wrong without telling you.
Truncated output becomes a smaller, valid object
// Input: the model hit max_tokens
{"users": [{"id": 1, "name": "Ada"}, {"id": 2, "name": "Bo
// jsonrepair output
{"users": [{"id": 1, "name": "Ada"}, {"id": 2, "name": "Bo"}]}The repaired JSON parses, and user 2 is now called "Bo". Any users after that are simply gone. This is the most dangerous failure, because nothing downstream will notice. Always check the stop reason first (stop_reason: "max_tokens" in the Anthropic API, finish_reason: "length" in OpenAI's Chat Completions API) and retry with a larger limit or a smaller task instead of repairing.
Prose around the JSON changes its shape
// Input
Sure! Here is the JSON you asked for:
{"name": "Ada", "role": "admin"}
// jsonrepair output
[
"Sure! Here is the JSON you asked for:",
{"name": "Ada", "role": "admin"}
]jsonrepair treats each line as a value and wraps them in an array. Trailing chatter such as "Hope this helps!" does the same. Your code expected an object and now gets an array. Extract the JSON span before repairing.
Repaired but wrong for your schema
A repaired object can still have a missing field, a string where you expected a number, or an invented enum value. Repair fixes syntax; only schema validation catches semantics. Our JSON Schema validator checks a repaired document against your schema in the browser.
How do I parse LLM JSON safely in code?
Put the checks in order: truncation, extraction, strict parse, repair, then validation. This TypeScript helper handles the first four. It was tested against the fence, prose, trailing-comma, Python-literal and comment cases above.
import { jsonrepair } from "jsonrepair";
export function parseModelJson(text: string, stopReason: string): unknown {
if (stopReason === "max_tokens") {
throw new Error("Truncated output: retry with a higher max_tokens");
}
const start = text.search(/[[{]/);
const end = Math.max(text.lastIndexOf("}"), text.lastIndexOf("]"));
const candidate = start >= 0 && end > start ? text.slice(start, end + 1) : text;
try {
return JSON.parse(candidate);
} catch {
return JSON.parse(jsonrepair(candidate));
}
}After parsing, validate with a JSON Schema validator such as Ajv and, on failure, send the validation errors back to the model in a retry. Models can usually act on precise errors such as a JSON path plus a message. Log every repair. If repairs suddenly spike, your prompt or model version changed, and you want to know.
Should I use structured outputs instead?
If your provider supports it, yes. Structured outputs constrain decoding to your JSON Schema, so the model cannot emit a trailing comma in the first place. Anthropic's structured outputs documentation promises "no more JSON.parse() errors" and states that structured outputs "guarantee schema-compliant responses through constrained decoding." It is generally available through output_config.format or strict: true on tools.
Two caveats keep a repair fallback useful. First, the same documentation notes that a refusal can take precedence over the schema and that output can be incomplete if max_tokens is reached. Second, only a subset of JSON Schema is supported: there are no numeric constraints such as minimum, no string-length constraints, and additionalProperties must be false. Our structured outputs comparison covers how the major providers differ.
| Approach | Prevents syntax errors | Catches truncation | Best for |
|---|---|---|---|
| Prompt only ("return JSON") | No | No | Prototypes |
| Prompt plus jsonrepair | Fixes after the fact | No, hides it | Models without structured outputs |
| Structured outputs | Yes | Only via stop reason | Production extraction |
| Structured outputs plus schema validation | Yes | Yes, with a stop-reason check | Anything that writes to a database |
Does the input format affect output errors?
Indirectly. Long prompts leave less room for the answer, which makes truncation more likely. If you feed large datasets into the prompt, a compact input format such as TOON uses about 43% fewer tokens than JSON on average and frees up room in the context window. Keep the output in JSON, though: models have far more JSON in their training data, and JSON is what structured outputs and validators support. See JSON vs TOON for when that split pays off, and how to convert XML to JSON if your source data starts as XML.
Frequently Asked Questions
Why does JSON.parse fail on LLM output?
Usually because the model wrapped the JSON in a Markdown code fence or a sentence of prose, used JavaScript or Python habits such as trailing commas, single quotes, True and None, added comments, or stopped mid-object when it hit the max_tokens limit. JSON (RFC 8259) allows none of these.
Is it safe to auto-repair JSON from a model?
It is safe for syntax problems such as trailing commas, quotes and comments, because the data is all there. It is not safe for truncated output, because the repair tool closes the open string and brackets and returns a valid but incomplete object. Check the stop reason and validate the repaired result against a schema.
Do structured outputs make JSON repair unnecessary?
Mostly. Schema-constrained decoding, such as Claude structured outputs, guarantees parseable, schema-compliant JSON in normal responses. Anthropic's documentation still lists two exceptions: refusals and responses cut off by max_tokens. Keep a repair-and-validate fallback for those cases and for models without structured output support.
Can I fix invalid JSON online without uploading it?
Yes. The json2toon.co JSON Repair tool runs jsonrepair in your browser, so the text you paste is not sent to a server. It fixes trailing commas, single and smart quotes, Python literals, comments, unquoted keys and truncated brackets, and shows the repaired JSON for you to copy.
Recommended Reading
How to Convert JSON to CSV (Including Nested JSON)
Convert JSON to CSV correctly: flatten nested objects, quote commas and line breaks per RFC 4180, handle arrays, and open the result cleanly in Excel.
TOON vs Minified JSON: When Compact JSON Wins
The latest TOON benchmark shows compact JSON beats TOON on mixed, nested data, while TOON wins big on uniform tables. Here is how to choose for your payload.
Token-Efficient Apps with TOON and the Vercel AI SDK
How to format context as TOON inside Vercel AI SDK apps to cut input tokens—while keeping generateObject and tool calls on JSON for reliable structured output.