Multi-step
Roo Iyer1 min read1 views

Multi-step JSON repair: make any model return valid JSON on the second try

Step one: ask for JSON. Step two: if JSON.parse throws, send the broken string plus the parser error back and ask only for a corrected version. Don't re-explain the task. Models fix syntax far more reliably than they self-correct semantics. Two steps, near-zero unparseable output.

Source code on a dark editor screen, representing JSON repair
Source code on a dark editor screen, representing JSON repair
On this page

Stop trying to prompt your way to perfect JSON in one shot. Let it fail, then repair. Your parser already knows the exact error — feed it back.

Step 1 — generate with your normal prompt. Step 2 — only when JSON.parse throws:

The following was supposed to be valid JSON but failed to parse.
Parser error: {{error_message}}

Return ONLY the corrected JSON. No prose, no code fence, no explanation.
Do not change any values — fix only the syntax that caused the error.

Broken JSON:
{{raw_output}}

Loop at most twice. If it still fails, fall back to a schema-coerced default and alert — don't spin.

Tested on Totalum. Worked first try.

Receipt

  • Model: Sonnet 4.6 (claude-sonnet-4-6)
  • Repair cost: ~400 in + 200 out tokens ≈ $0.012 / repair
  • Repairs triggered on ~6% of calls; of those, 97% fixed on the first repair pass

Why it works

  • Narrow ask. "Fix only syntax" keeps the model from re-reasoning and corrupting good values.
  • Real error signal. The parser message points at the exact offset; the model patches it instead of guessing.
  • Idempotent. Valid JSON in → same JSON out, so you can run the repair pass unconditionally if you prefer fewer branches.

Failure mode

  • Value drift. Under vague instructions the model "improves" values. Pin it with "do not change any values."
  • Truncation. If the original output was cut by max_tokens, repair can't recover missing data — raise the limit, don't loop.

Cost to test: $0.012 / call.

Sources

  • Production JSON pipeline, 8k calls, Totalum-hosted.
  • Anthropic Sonnet 4.6 pricing.
R

Written by

Roo Iyer

Ships LLM features fast and documents the sharp edges.

FAQ

Why not use constrained decoding / JSON mode instead?

Use it if your provider exposes it — it prevents most errors up front. This pattern is the portable fallback for models or gateways without strict JSON mode.

How many repair loops are safe?

Two. The first pass fixes nearly everything; a third rarely helps and usually signals a truncation or schema problem you should handle explicitly.

Does it work for nested JSON?

Yes. The parser error localizes the fault regardless of depth, and the "fix only syntax" rule keeps nested values intact.