Common JSON Syntax Errors and How to Fix Them
JSON fails to parse when the text breaks one of the grammar rules in RFC 8259, and the usual culprits are a small, predictable set: trailing commas, single quotes, unquoted keys, comments, raw line breaks inside strings, and JavaScript-only values such as NaN or undefined. The fix is to find the first position the parser complained about, look at the character just before it, and correct that one mistake before re-validating. This guide lists each error, why it happens and how to fix it.
How to find the error quickly
A JSON parser reads from left to right and stops at the first character it cannot accept. That point is where it noticed the problem, which is often just after the real mistake. A missing comma, for example, is reported at the start of the next key, not at the end of the previous value.
Paste the document into the JSON Formatter and click Validate (or Beautify). The page uses the browser's own JSON.parse, so the wording of the message comes from your browser and differs between Chrome, Firefox and Safari. When the browser's message includes a character position, the tool converts it into a line and column and appends it, for example (Line 3, Column 3). Some messages carry no position (V8-based browsers report an unexpected token such as NaN by quoting the input instead); then you see the browser's message unchanged.
Take this document with a missing comma:
{
"name": "Ada"
"age": 36
}
In a V8-based browser such as Chrome the message reads Expected ',' or '}' after property value in JSON at position 20, and the formatter adds (Line 3, Column 3). Line 3, column 3 is the opening quote of "age"; the comma belongs at the end of line 2. Fix one error at a time and validate again.
Error, cause and fix at a glance
| Invalid input | Cause | Fix |
|---|---|---|
{"a": 1,} | Trailing comma | {"a": 1} |
{'a': 'x'} | Single quotes | {"a": "x"} |
{a: 1} | Unquoted key | {"a": 1} |
{"a": 1 // note} | Comment | Remove it or move it into a field |
A raw line break inside "..." | Unescaped control character | Write \n |
"it\'s", "\x41" | Escape JSON does not define | "it's", "\u0041" |
NaN, Infinity, undefined | Not JSON values | null or a string |
012, .5, 5., +1, 0x1F | Invalid number form | 12, 0.5, 5.0, 1, 31 |
{"a": [1, 2} | Unbalanced brackets | {"a": [1, 2]} |
{"a":1}{"b":2} | Two documents in one | Wrap in an array or parse line by line |
Trailing commas
JSON allows a comma only between members or elements, never after the last one. Both {"a": 1,} and [1, 2,] are invalid, even though JavaScript, Python and many config formats accept them. Delete the comma before the closing } or ]. Because the parser only notices when it reaches the bracket, the reported position points at the bracket rather than the comma.
Quotes: single quotes, unquoted keys and smart quotes
Strings and object keys must use straight double quotes (", U+0022). Single quotes, bare identifiers as keys ({name: "Ada"}), numeric keys ({1: "a"}) and typographic quotes such as “name” pasted from a word processor or chat app are all rejected at the first character of the key. The fix is always the same: wrap every key in double quotes and convert every string to double quotes, escaping any double quote that appears inside the text as \". A single quote inside a double-quoted string needs no escaping at all.
Comments
JSON has no comment syntax. Neither // line nor /* block */ comments are allowed, and a strict parser fails at the first slash. If you need to keep a note, store it as data, for example "_comment": "...", or keep the commented original and strip comments before handing it to a strict parser.
Strings: control characters and invalid escapes
Inside a JSON string, the characters U+0000 to U+001F must be escaped. In practice this means a literal line break or tab inside quotes is an error (V8 calls it a bad control character in a string literal). Write \n, \r or \t instead.
Only these escapes exist: \", \\, \/, \b, \f, \n, \r, \t and \uXXXX with exactly four hex digits. Escapes borrowed from other languages fail: \' (just write the apostrophe), \x41 (use \u0041), and \u00g9 (not hex). A lone backslash in a Windows path is the most common case: "C:\temp" is read as a tab followed by emp, and "C:\data" is rejected because \d is not an escape. Double the backslashes: "C:\\data".
The easiest way to get this right is not to escape by hand. Paste raw text into String Escape / Unescape and click Escape; the tool runs JSON.stringify on the text, so the output is a complete JSON string literal, surrounding double quotes included. In code, build the value as a native string and let the serialiser escape it:
JSON.stringify("line1\nline2\t\"quoted\"\\");
// "line1\nline2\t\"quoted\"\\"
Values that are not JSON: NaN, Infinity and undefined
JSON has exactly six kinds of value: object, array, string, number, true/false and null. The literals are lower case, so True and NULL fail. NaN, Infinity, -Infinity and undefined are JavaScript values with no JSON representation.
These often come from a serialiser rather than a person. Python's json.dumps(float("nan")) writes NaN by default, which JavaScript's JSON.parse rejects; pass allow_nan=False to make Python raise an error instead of producing invalid output. JavaScript goes the other way: JSON.stringify turns NaN and Infinity into null, drops object properties whose value is undefined or a function, and writes null for them inside arrays. Decide what a missing or non-finite value should mean and encode it explicitly, as null or a string such as "NaN".
Number rules
A JSON number is an optional minus sign, an integer part, an optional fraction and an optional exponent. That rules out several forms that are legal in programming languages:
- Leading zeros:
012is invalid;0on its own and0.12are fine. Codes with leading zeros belong in strings:"012". - Missing digits around the point:
.5and5.are invalid; write0.5and5or5.0. - Plus sign, hex, octal, binary, underscores:
+1,0x1Fand1_000are not allowed. - Exponents are allowed:
1e2,1E-3.
Valid numbers can still lose information. JavaScript stores every number as a 64-bit float, so JSON.parse("9007199254740993") returns 9007199254740992, and 1E400 becomes Infinity. RFC 8259 warns that interoperability is only good within the range and precision of IEEE 754 double precision; send large IDs and exact decimals as strings.
Duplicate keys
{"a": 1, "a": 2} is not a syntax error: the grammar permits it, and every validator, including the JSON Formatter, accepts it. RFC 8259 only says that names within an object SHOULD be unique, and notes that otherwise the behaviour of receiving software is unpredictable. JavaScript's JSON.parse and Python's json.loads both keep the last value, but other parsers may keep the first, report an error or keep both. Because the formatter re-serialises the parsed object, Beautify and Minify silently drop the earlier duplicate, which is a quick way to spot one: compare the output with the input. Treat duplicates as a bug in whatever produced the document.
Byte order mark (BOM) and invisible characters
Files saved as "UTF-8 with BOM" begin with the invisible character U+FEFF. RFC 8259 says a BOM must not be added to JSON sent over a network and that parsers may ignore one, so parsers differ: JSON.parse rejects a string that starts with it, and Python's json.loads raises an error suggesting the utf-8-sig codec. The JSON Formatter trims the input before parsing, which removes a leading BOM, so a file can validate here and still fail in your application. Save the file as UTF-8 without BOM. Non-breaking spaces (U+00A0) copied from web pages or documents are a similar trap: they look like spaces but are not JSON whitespace, so they fail when they appear between tokens.
Truncated documents and unbalanced brackets
If a response was cut off, a log line was truncated or a bracket was deleted, the parser either reaches the end of the input early (V8 says "Unexpected end of JSON input") or meets the wrong closing bracket, as in {"a": [1, 2}. Use your editor's bracket matching to see where nesting goes wrong. In application code, the same error from an empty string often means an HTTP request returned an empty body rather than malformed JSON.
Several documents in one: concatenation and NDJSON
A JSON text is exactly one value. {"a":1}{"b":2}, or two objects on separate lines, fails after the first value with an error about unexpected content after the JSON. Newline-delimited JSON (NDJSON, also called JSON Lines) is a common format for logs and bulk exports, but it is a sequence of documents, not one, so parse it line by line:
const records = text
.split("\n")
.filter(line => line.trim() !== "")
.map(line => JSON.parse(line));
To validate a single record in the formatter, paste one line at a time, or wrap the records in [ ... ] and separate them with commas.
JSON versus JavaScript object literals
JSON's syntax was taken from JavaScript, but a JavaScript object literal is a much larger language. Code copied from a .js file or a browser console often contains features JSON never had:
// Valid JavaScript, invalid JSON
const user = { name: 'Ada', tags: ['x',], active: true, score: NaN, // note
created: new Date(), greet() {} };
// Valid JSON
{"name": "Ada", "tags": ["x"], "active": true, "score": null, "created": "2026-10-03T00:00:00.000Z"}
Rather than editing the literal by hand, run JSON.stringify(user, null, 2) in the console and copy the result; it quotes keys, converts dates to ISO strings and drops functions. Never use eval() to "parse" JSON that a strict parser rejects, because that executes the text as code.
Checklist
- Every key and string uses straight double quotes.
- No comma after the last item in any object or array.
- No comments, no
NaN,Infinityorundefined; literals are lower case. - Line breaks and tabs inside strings are written as
\nand\t; backslashes are doubled. - Numbers have no leading zeros, plus signs or bare decimal points; large IDs are strings.
- Keys within each object are unique.
- The file is UTF-8 without a BOM and holds exactly one top-level value.
- Fix the first reported error, then validate again.
Frequently asked questions
Is a plain string or number valid JSON on its own?
Yes. RFC 8259 allows any JSON value at the top level, so "hello", 42 and null are valid documents. Older software written for the earlier RFC 4627 may still expect an object or array.
Can I add comments to a JSON config file?
Not in standard JSON. Some tools accept a relaxed dialect for their own config files, but a strict parser will fail. Use a field such as "_comment", or choose a format with comments such as YAML; see YAML pitfalls before switching.
Why does my file validate in the formatter but fail in my app?
The formatter trims leading and trailing whitespace, including a byte order mark, before parsing. If your application reads the raw bytes, a BOM or an encoding other than UTF-8 can still break it.
Does JSON allow duplicate keys?
The grammar does, but RFC 8259 says names SHOULD be unique because parsers handle duplicates differently. JavaScript and Python keep the last value; other parsers may keep the first or reject the document.