GUIDES /

Fix invalid JSON: read the error message, apply the exact fix

18 invalid JSON snippets run through a real formatter with their exact error messages and positions — a message-to-fix dictionary, plus strict JSON vs JavaScript and LLM-output traps.

Short answer: JSON breaks in a small number of ways — quotes, commas, brackets, escapes, and look-alike literals from other languages. A validator tells you *where* it broke and *what* the parser expected; this guide maps the exact messages to the exact fix. One honest scope note: the YYSI formatter validates, locates, formats, minifies, sorts and diffs — it does not auto-repair. You apply the fix yourself; that is safer, because a "repair" that changes syntax can also change meaning (think 007 becoming 7).

The error dictionary (all messages verified in the real tool)

Each row below was produced by pasting the sample into the live formatter and recording what its parser said. Positions are from that parser; other tools may point elsewhere — the *cause* and *fix* columns are what transfer.

What you pastedWhat the parser said (real)Meaning → exact fix
{'name': 'YYSI'}Line 1, column 2: Expected object keyJSON strings use double quotes only → "name": "YYSI"
{"a": 1, "b": 2,}column 31: Expected object keyTrailing comma before } — the parser now expects another key → delete the last comma
["news", "tools",]column 18: Unexpected character "]"Trailing comma in an array → delete it
{"a": 1 "b": 2}column 9: Expected "," or "}"Missing comma between pairs → add ,
{"timeout" = 30}column 12: Expected ":" after keyAssignment syntax → use : not =
{"user": {"name": "Ada"... (one } missing)column 33: Expected "," or "}"A nested object never closed at EOF → add the missing } (when input simply stops mid-structure the message is Unexpected end of input)
``json\n{...}\n`` (Markdown fence)Line 1, column 1: Unexpected character "`"Copy from a chat/LLM window → delete the fence lines, keep the JSON between them
{"quote": "He said "hi" fast"}column 21: Expected "," or "}"The inner quote *ends* your string early → escape inner quotes: \"hi\"
{"text": "line1␊line2"} (real newline)column 16: Unescaped control character in stringRaw line breaks are invalid inside strings → write \n
{“name”: “YYSI”} (curly quotes)column 10: Unexpected character "“"Word processors replace straight quotes with curly ones → retype as ASCII "
{"delta": +1}column 11: Unexpected character "+"JSON numbers can't start with + → drop it
{"zip": 007}column 10: Expected "," or "}"Leading zeros are forbidden in JSON numbers → if it is a code/ID, store it as a string: "007"
{"mask": 0x1F}column 11: Expected "," or "}"No hexadecimal in JSON → write decimal 31
{"ok": True, "x": None}column 8: Unexpected character "T"Python literals → JSON uses lowercase true / false / null
{"score": NaN}column 11: Unexpected character "N"NaN/Infinity are JavaScript, not JSON → use null or a real number
{name: "YYSI"} (unquoted key)column 2: Expected object keyKeys must be quoted strings → {"name": "YYSI"}
// comment after or inside valuesExpected "," or "}" (inside) / Unexpected trailing content (after a complete document)JSON has no comments → move the note outside the data
empty inputLine 1, column 1: Unexpected end of inputNothing to parse → the file may have been saved empty
Note:All 18 samples and their corrected versions are downloadable below — every message in the table is reproducible from them.

Step by step with the real tool

  1. Paste and read the status. Paste your text into the formatter. While you type it shows Valid JSON · N bytes or Invalid JSON.
  2. Press Format to locate the error. On invalid input the tool reports the position and the parser's complaint, e.g. Error at line 1, column 1: Unexpected character ""` for a Markdown fence. Find that line/column in your text.
  3. Match the message to the dictionary above. Apply the one-character or one-line fix. Re-format to confirm the error is gone — positions shift as you edit, so fix the *first* reported error, then retry.
  4. Format, minify or sort. Once valid: Format re-indents (2 spaces, 4 spaces or tab), Minify strips whitespace, Sort orders object keys alphabetically at every depth.
  5. Copy or download. Copy to clipboard or download yysi-formatted.json. Both activate only after a successful parse.
  6. Compare two versions. Paste the second JSON into the compare box and press Diff: changes, additions and removals are listed per path with array length changes — useful for checking that your fix changed nothing else.

Our real diff example

Diffing {"model": "flash", "retries": 3, "cache": true, "tools": ["search"]} against {"model": "pro", "retries": 3, "cache": false, "tools": ["search", "code"], "note": "nov"} produced exactly:

CHANGED $.model  "flash" → "pro"
CHANGED $.cache  true → false
CHANGED $.tools  length 1 → 2
ADDED   $.tools[1]  "code"
ADDED   $.note  "nov"

Strict JSON vs JavaScript object literal

Most "broken JSON" is actually a JavaScript object literal (or Python dict) — a different language. JSON (RFC 8259) allows neither single quotes, nor bare keys, nor trailing commas, nor comments, nor +/hex/leading-zero numbers, nor True/None. Editors and consoles accept those because they evaluate *code*, not *data*. If your text came from a JS/Python file, expect to convert all of these; if it came from a log, also expect unescaped quotes and raw newlines inside strings.

LLM output is its own genre

  • Markdown fences (`` or `json) around the payload — the single most common error when copying from chat windows; our sample reproduces Unexpected character "" at column 1.
  • Trailing commas and single quotes — models imitate the training data's JavaScript.
  • Comments explaining the fields — models narrate; JSON cannot.
  • Fix order: delete fences → fix quotes/commas → remove comments → validate. Then re-paste the *final* value; never ship a fix you haven't re-parsed.
Warning:A formatter that "auto-repairs" can silently change data: 007 → 7 turns a part number into a different number, and deleting a trailing comma is fine but deleting a "duplicate" key is a data decision. Validate and fix deliberately; check numbers and IDs after any automated repair.

Edges the tool tells you about honestly

InputWhat the tool does (verified)Why it matters
{"order_id": 9007199254740993}Parses it, formats it, keeps the original digits and shows a warning listing the path (order_id) — because the value exceeds JavaScript's safe integer range (2^53−1)Naive parsers silently turn …993 into …992; the warning tells you a downstream consumer may do exactly that
{"a": 1, "a": 2} (duplicate keys)Accepts the text; the later value wins ({"a":2}) — standard parser behavior, no warningDuplicate keys are ambiguous data; if you did not write them on purpose, deduplicate by hand
Anything validFormat / Minify / Sort are pure re-serialization — values, key order (except Sort) and number spelling are preservedFormatting never changes meaning; sorting never changes values

Limits

  • The formatter is strict and offline: no repair, no schema validation, no network calls.
  • Error positions are this parser's opinion; browsers, Python and other tools may point to different columns for the same broken text — treat positions as a starting hint, the message class as the truth.
  • Everything runs in your browser tab; the text never leaves your device.
  • Very large inputs are limited by browser memory like any text box; for multi-megabyte payloads use a local tool instead.

Related: turning fixed JSON tabular? JSON ↔ CSV converter — and if CSV then misbehaves in Excel, read the CSV garbled-Chinese troubleshooting guide.

Sources & verification

Sources checked The grammar rules summarized here come from RFC 8259 and MDN (checked 2026-11-11). Every error message, line/column position and behavior in the tables was produced by running the original sample set through the live YYSI JSON formatter's own parser on 2026-11-11 (18 invalid snippets + fixed pairs, plus format/minify/sort/diff/big-number demos). The samples are original synthetic text, published for reuse.

Read our editorial standards or send corrections to [email protected].