Valid JSON is strict. Humans and language models are not. You end up with a blob that is almost JSON: a trailing comma after the last property, single quotes instead of double, a comment someone swore was fine, an object cut off mid-stream. JSON.parse throws, your pipeline stops, and you are staring at a bracket-counting exercise on a deadline.

This guide walks through the errors you actually hit, how to fix each one by hand, the libraries that automate it, and why LLM output breaks in its own special ways. At the end there’s a one-call option for when you’d rather not maintain a repair function forever.

The Six Ways JSON Breaks (and the Fix for Each)

1. Trailing commas

The single most common one. JSON, unlike JavaScript, forbids a comma after the last element.

{ "a": 1, "b": 2, }      // ✗ invalid
{ "a": 1, "b": 2 }       // ✓ fixed

Fix: delete the comma before every } and ]. A regex like /,(\s*[}\]])/g$1 handles it in bulk.

2. Single quotes and smart quotes

JSON strings must use straight double quotes. Copy from Word, Slack, or Notion and you often get curly “smart” quotes; write it like JavaScript and you get single quotes.

{ 'name': 'Ada' }        // ✗ single quotes
{ “name”: “Ada” }        // ✗ smart quotes
{ "name": "Ada" }        // ✓ straight double quotes

Fix: replace ‘ ’ “ ” with ", but be careful not to clobber apostrophes inside string values, which is exactly why a real parser beats a blind find-and-replace.

3. Unquoted keys

{ name: "Ada" }          // ✗ key not quoted
{ "name": "Ada" }        // ✓

Fix: quote every key. This is valid JavaScript and valid JSON5, but not valid JSON.

4. Comments

JSON has no comments. A // like this or /* like this */ anywhere in the payload is a hard error. Fix: strip them, but not if the // lives inside a URL string, another parser-vs-regex trap.

5. Truncated / cut-off output

The classic LLM failure: the model hit its token limit mid-object and the string just… stops. Fix: close the open brackets, or (better) re-request with a higher max_tokens. Repair can only guess at data that was never generated.

6. Prose wrapped around the JSON

“Sure! Here is your JSON:” followed by a fenced code block. Fix: extract the substring between the first { (or [) and its matching close, and discard the rest.

Don’t Hand-Roll It: The Tools That Do This

For anything beyond a one-off, use a library built for lenient parsing instead of a stack of regexes:

  • JavaScript / TypeScript: the jsonrepair npm package, or parse as JSON5 which natively allows comments, trailing commas, and unquoted keys.
  • Python: the json-repair package, or demjson3 for forgiving parsing.
  • Command line: jq won’t fix malformed input, but it’s the fastest way to validate and pretty-print once the syntax is clean.

Why LLM JSON Breaks Differently

Language models generate JSON token by token with no guarantee the result parses. They over-run their token budget, wrap output in explanation, escape strings inconsistently, and occasionally invent a trailing comment. The durable fix is upstream: use your model’s structured-output or JSON mode (constrained decoding), which forces syntactically valid output at generation time. Repair is the safety net for when you can’t control the generator: a third-party API, an older model, a tool you don’t own.

Repair JSON as a $1 / x402 call

When you’d rather call an endpoint than maintain a repair function, JSON repairer takes the broken string and returns valid JSON when repair is possible. Humans pay $1 per call in the browser; agents call POST https://gate402.app/v1/json-repair, handle the 402 Payment Required, pay, and retry. It is the same pattern across the whole Gate402 utility set. Handy inside an agent loop that emits broken JSON every few calls and needs to self-heal without a human.

When Repair Is the Wrong Tool

If the model omitted half the schema, “repair” may invent structure you should not trust. Prefer repair for syntax damage, then always validate against your schema (JSON Schema, Zod, Pydantic) afterward. Garbage semantics (missing required fields, wrong types) need a better prompt or structured output, not a syntax patch.

Quick answers

Is repaired JSON safe to trust?

For syntax fixes (commas, quotes, brackets), yes. For truncated or semantically incomplete data, no. Validate against a schema before you rely on it.

How do I stop the LLM producing broken JSON in the first place?

Use the provider’s structured-output / JSON mode, give it a schema, and set a max_tokens high enough that it doesn’t truncate.

What about CSV that needs to become JSON?

Different job. That’s the CSV ↔ JSON tool.

What to do next time

Don’t hand-edit trailing commas in a production agent path. Fix the generator where you can (structured output), use a real lenient parser where you can’t, and validate the result against a schema before trusting it. When you want that as an endpoint instead of a gist you maintain forever, repair JSON for $1, or over x402 for agents.