Skip to content
jsonforge.app
Back to blog
Guide7 min read

Common JSON Parsing Errors and How to Fix Them

JSON.parse() doesn't do partial parsing and it doesn't guess at intent — a single misplaced character anywhere in a multi-megabyte document throws the same generic SyntaxError as a single misplaced character in a five-line config file. This guide walks through the errors you'll actually hit in V8 (Node.js and Chrome), what each one is really telling you, and how to decide between fixing it by hand and running it through an automated repair tool.

Why JSON.parse throws instead of guessing

JavaScript object literals are forgiving: unquoted keys, trailing commas, single-quoted strings, and even comments are all legal, because the source is parsed by the same engine that parses everything else. JSON is not JavaScript — it's a much smaller, stricter grammar (RFC 8259), and JSON.parse() enforces every rule of that grammar with no fallback. There's no 'mostly correct' JSON; the parser reads left to right and stops dead at the first token that doesn't fit the grammar at that position.

That's a deliberate design choice, not a limitation: a lenient JSON parser would silently accept subtly different documents in different implementations, which is exactly the interoperability problem JSON was invented to avoid. The cost is that error messages are terse and positional rather than semantic — the parser tells you where the grammar broke, not what you meant to write.

Trailing commas

The single most common JSON error is a trailing comma left over from editing a JavaScript object literal (where it's legal) and forgetting it isn't legal in JSON.

A trailing comma after the last array/object entry is invalid JSON.
json
{
  "name": "Alice",
  "roles": ["admin", "editor"],
}

V8 rejects this at the closing brace, not at the comma, because the comma itself is valid grammar right up until the parser expects another property and finds `}` instead. Depending on your Node/Chrome version you'll see something like `Unexpected token '}', "...editor"],\n}"... is not valid JSON` (newer V8, with a snippet) or the older, terser `Unexpected token } in JSON at position 47`. Either way, the fix is the same: delete the comma before the closing bracket or brace.

Single quotes and unquoted keys

JSON requires double quotes for every string and every key — no exceptions. Single-quoted strings and bare (unquoted) keys are both extremely common when JSON is hand-typed or copy-pasted from JavaScript source.

Both of these are invalid JSON, even though they're valid JS object literals.
json
{ 'name': 'Alice' }
{ name: "Alice" }

A leading single quote produces something like `Unexpected token ''', "{ 'name'"... is not valid JSON`. An unquoted key is subtly different: modern V8 recognizes that a property name was expected and reports `Expected property name or '}' in JSON at position 2`, rather than blaming the bare identifier directly. Either way, the fix is mechanical — wrap every key and every string value in double quotes.

Unescaped newlines and control characters inside strings

A raw newline, tab, or other control character (anything below U+0020) inside a JSON string is illegal — it must be escaped as `\n`, `\t`, and so on. This bites most often when JSON is generated by naively concatenating a multi-line value (a log message, a code snippet, a user comment) into a string literal without escaping it first.

A literal line break inside the string value, not escaped.
json
{
  "message": "line one
line two"
}

This produces `SyntaxError: Bad control character in string literal in JSON at position 21` — one of the few JSON errors that names the actual problem instead of just a token. The fix is to escape the character rather than let it appear raw: `"line one\nline two"`.

Duplicate keys, NaN/Infinity/undefined, and BOM characters

Three quieter failure modes worth knowing by name. First, duplicate keys in a JSON object are not a parse error at all — `{ "id": 1, "id": 2 }` parses successfully, and JSON.parse silently keeps the last occurrence (`id: 2`) and discards the first. RFC 8259 says names 'should' be unique but doesn't require parsers to reject duplicates, so this is spec-compliant, easy-to-miss-in-review behavior rather than a bug in your parser.

Second, `NaN`, `Infinity`, and `undefined` are all valid JavaScript but none of them are valid JSON tokens — JSON only has `number`, not the IEEE-754 special values, and has no concept of `undefined` at all (only `null`). `{ "value": NaN }` throws `Unexpected token 'N', ..."value":NaN}"... is not valid JSON` (or `Unexpected token N in JSON at position 10` on older engines). If you're serializing from JavaScript, `JSON.stringify` already converts `NaN`/`Infinity` to `null` and drops `undefined` values entirely — the error usually means the JSON was hand-written or came from a non-JS source that assumed JS semantics.

Third, a UTF-8 byte-order-mark (U+FEFF) at the very start of a file — often added silently by Windows editors or some Java/.NET tools when saving UTF-8 — breaks `JSON.parse` when the file is read as a raw string, producing `Unexpected token '\ufeff'... is not valid JSON` at position 0. Note that this is a `JSON.parse`-on-a-string problem specifically: `Response.json()` in the Fetch API decodes UTF-8 text and strips a leading BOM as part of that decode, so the same bytes served over HTTP and read from disk with `fs.readFileSync(path, 'utf8')` can behave differently.

Reading the position, and when to reach for a repair tool

The `position` in a JSON.parse error is a zero-indexed character offset into the exact string you passed in, not a line number — Node (v20+) additionally computes and appends a `(line X column Y)` for convenience, but older runtimes and browsers only give the raw offset. Two things trip people up: the reported position is where the parser noticed the grammar was broken, which for a trailing comma or a missing bracket is often one token after where you actually made the mistake; and if you've pretty-printed the JSON for readability but are debugging the original minified string, the offsets won't line up with what you're looking at on screen.

For a one-off syntax slip in a short document, fixing it by hand once you've located the position is faster than any tool — paste it into a validator that highlights the exact character rather than counting offsets manually. For a large file with several unrelated errors, JSON generated by a buggy upstream tool, or JSON that's been through several rounds of lossy copy-paste, hand-fixing stops being worth the time. That's the point to reach for something automated: JsonForge's JSON Validator pinpoints every schema violation with a precise path once the document at least parses, and JSON Repair takes a pass at fixing common structural mistakes (missing quotes, trailing commas, mismatched brackets) automatically when the input is too mangled to fix one error at a time.

FAQ

Why does JSON.parse fail on a file that looks completely fine?
The most common invisible culprits are a leading byte-order-mark (BOM) character, and 'smart quotes' or em-dashes introduced by copy-pasting from a word processor, chat app, or PDF — both look identical to a plain double quote or hyphen in most fonts but are different Unicode characters that JSON.parse rejects. Open the file in an editor that can reveal hidden/non-ASCII characters, or diff it against a known-good version.
Why isn't a duplicate key treated as an error?
The JSON specification (RFC 8259) says object member names 'should' be unique but doesn't mandate that parsers enforce it, so behavior is implementation-defined. JavaScript's JSON.parse silently keeps the last duplicate and drops earlier ones; some other languages' parsers throw, and some keep the first occurrence instead. Never rely on duplicate-key behavior being consistent across environments.
Can I make JSON.parse accept trailing commas or comments?
Not JSON.parse itself — it strictly implements the JSON grammar with no options for leniency. If you need comments or trailing commas, use a JSON superset parser like JSON5 or a JSONC-aware parser, or strip the offending syntax before calling JSON.parse. Don't try to write your own regex-based stripping for anything beyond throwaway scripts — it's easy to accidentally corrupt commas or braces that appear inside string values.
What's the fastest way to find an error's exact location in a huge file?
Don't count characters by hand. Paste the document into a formatter or validator that visually highlights the exact offending line and column — that turns a multi-minute manual count into an instant lookup, especially once the file is large enough that the raw character offset is meaningless to a human.

Try these tools

Related articles