The JSON Errors You Actually Hit, and What the Parser Is Telling You
JSON is a subset of JavaScript with the friendly parts removed. That is the entire explanation for why a file that “looks fine” refuses to parse: the syntax you are mentally pattern-matching against is JavaScript object literal syntax, and JSON forbids most of it. This page runs every common violation through a real parser and prints the exact message, so you can match your error to a cause in a few seconds.
What JSON forbids that JavaScript allows
Each row below was fed to JSON.parse on the runtime noted at the end of the page; the message column is verbatim.
| Input | What is wrong | Parser says |
|---|---|---|
{"a":1,} | trailing comma | Expected double-quoted property name in JSON at position 7 (line 1 column 8) |
{'a':1} | single quotes | Expected property name or '}' in JSON at position 1 (line 1 column 2) |
{a:1} | unquoted key | Expected property name or '}' in JSON at position 1 (line 1 column 2) |
{"a":1 /* x */} | comment | Expected ',' or '}' after property value in JSON at position 7 (line 1 column 8) |
{"a":NaN} | NaN literal | Unexpected token 'N', "{"a":NaN}" is not valid JSON |
{"a":0x10} | hexadecimal | Expected ',' or '}' after property value in JSON at position 6 (line 1 column 7) |
{"a":01} | leading zero | Unexpected number in JSON at position 6 (line 1 column 7) |
{"a":+1} | plus sign | Unexpected token '+', "{"a":+1}" is not valid JSON |
Read the messages as coordinates rather than advice. V8 reports a zero-based character offset and a one-based column, so “position 7 (line 1 column 8)” points at the same byte: the character after the comma. When the offset is at the very end of the document, the real problem is usually something missing rather than something wrong — an unclosed brace or string two lines up.
The trailing comma is the one that comes back
It is legal in JavaScript array and object literals, it is produced by hand-editing a list, and it is produced by generators that join elements with a comma and then append an empty one. JSON does not allow it. If you are building JSON by string concatenation in a shell loop, this is your bug; build a real array and serialise it once.
Two errors that do not fail at all
These are the dangerous ones, because the parse succeeds and the data is wrong.
Duplicate keys. {"a":1,"a":2} parses without complaint and yields {"a":2}. The first value is silently discarded. If a config file has a duplicated key, whichever comes last wins, and a diff tool that sorts keys will change the meaning of the file.
Numbers that overflow. JSON has no infinity, but 1e999 parses to Infinity on this engine. Serialise that object and the value becomes null. A pipeline that parses, mutates and re-emits can therefore turn an overflowed number into a null without a single error message — which is how “the API returned null for total” bugs get written.
Strings are stricter than they look
| Input inside a string | Verdict | Parser says |
|---|---|---|
| raw newline | forbidden | Bad control character in string literal in JSON at position 11 (line 1 column 12) |
| raw tab character | forbidden | Bad control character in string literal in JSON at position 7 (line 1 column 8) |
| escaped \\n or \\t | fine | use the two-character escape |
| unterminated string | fatal | Unterminated string in JSON at position 8 (line 1 column 9) |
Any control character below 0x20 must be escaped, and the only escapes JSON defines are \" \\ \/ \b \f \n \r \t and \uXXXX. There is no \x41 and no \u{1F600}; an emoji outside the basic plane is either written literally as UTF-8 or as a surrogate pair. Copy-pasting JSON out of a chat client or a word processor is a reliable way to acquire raw control characters and typographic quotes, both of which are invisible in most editors.
The byte-order mark
A UTF-8 file that begins with an invisible BOM fails with a message that names no useful location: SyntaxError: Unexpected token '', "{"a":1}" is not valid JSON. This shows up constantly on Windows-generated files and in CSV-to-JSON exports. Strip the first three bytes (EF BB BF) or re-save as UTF-8 without BOM.
Structural mistakes and empty input
| Case | Parser says |
|---|---|
| mismatched bracket | Expected ',' or ']' after array element in JSON at position 9 (line 1 column 10) |
| empty input | Unexpected end of JSON input |
| BOM only | see above |
An empty body is one of the most common production errors, because an HTTP client that returns 200 with no body produces a parse failure that looks like a syntax problem. Check the length before you check the syntax.
A 60-second order of operations
- Look at the reported position first, then read two tokens backwards from it — missing delimiters hide upstream.
- Search for , immediately before } or ]. That is the trailing comma.
- Search for //, /* and '. Comments and single quotes are not JSON.
- Reveal invisible characters, or hex-dump the first 16 bytes to catch a BOM.
- If the document is large, bisect: parse the first half, then the second. A formatter that reports a position is worth more than a linter that reports a count.
- If you are generating the file, print it from a data structure instead of writing it out by hand, and the whole class of error disappears.
How the formatter on this site reports it
The JSON Formatter calls the browser’s own parser, so the message you see is the one from your engine rather than a paraphrase written by us — which is why the wording differs between Chrome, Firefox and Safari even when the diagnosis is the same. It re-indents with two spaces, minifies back to one line, and can sort keys recursively. On the key-sorting point: sorting makes two files comparable, but as shown above it can also change which duplicate key survives, so sort for diffing, not for shipping.
One practical note on engines: the exact messages and offsets above were captured on Node v24.19.0 / V8 13.6.233.17-node.51. Chrome’s V8 is the same family, so the text will usually match; Firefox’s SpiderMonkey words the same complaints differently. What transfers across every engine is the position, so trust the offset over the prose.
Frequently asked questions
Is JSON with comments ever valid?
Not as a data interchange format. JSON5 and JSONC are supersets that some tools accept; if a file needs comments, either accept that it is not JSON or move the comment into a field such as “_comment”, which is valid JSON.
Why does my CSV-to-JSON output fail?
Almost always an unescaped quote or a stray control character from the source file, plus the BOM. Numbers exported as text with leading zeros also fail if something tries to write them as bare numbers.
Does key order matter?
Not for validity, and not for most consumers. It matters for hashing, caching and diffing two files — which is why a sort option exists on the formatter.
Can JSON store dates?
No date type exists. The conventions are ISO-8601 strings or integer epoch milliseconds; both parse happily as a string and a number, and neither is checked for you.
Related tools
JSON Formatter & Validator
Indent, minify, sort keys and locate the exact position of a syntax error. Free browser-based tool on this site. Runs locally, nothing is uploaded.
CSV to JSON
Convert delimited text into an array of objects, with header and delimiter options.
JSON to CSV
Flatten an array of objects back into a spreadsheet-shaped file.
Text Diff
Compare two documents side by side once both parse.
Written and maintained by CHENYUWEN. First published 2026-10-30. If something here is wrong, tell us - corrections are dated on the page.