How to Debug JSON Syntax Errors: Fix Unexpected Tokens & Commas
There are few runtime exceptions as universally frustrating to a developer as SyntaxError: Unexpected token in JSON at position X. You dispatch a network request, receive a payload, run JSON.parse(), and your entire application crashes.
Unlike standard JavaScript object literals, which are highly permissive, JavaScript Object Notation (JSON) is an unforgiving, strict data-interchange format governed by RFC 8259. A single misplaced comma, an unescaped line break, or a silent API failure will instantly break the parsing engine.
When a JSON parser fails, it evaluates the byte stream sequentially from left to right. The moment it encounters a character that violates strict structural grammar, it halts and throws an exception. Understanding the exact context of these frequent errors is the fastest way to isolate and repair broken data pipelines.
1. The API Trap: `Unexpected token < at position 0`
This is the most frequent JSON error encountered in frontend development. Ironically, it is almost never a JSON syntax error.
Notice the specific character the parser chokes on: the less-than symbol (<) at position 0 (the very first byte of the response). What common web format begins with an angle bracket? HTML error pages.
The Root Cause:
Your application requested a JSON endpoint, but the server responded with an HTML error page. This usually happens when an API gateway returns a 404 Not Found, a 500 Internal Server Error, or an intercepting security proxy returns an HTML CAPTCHA challenge. When your code blindly calls response.json() on that HTML string, the parser crashes on the first bracket.
The Debugging Fix
Do not attempt to fix the JSON—you must fix the network request. Always verify the HTTP response status and the Content-Type header before parsing:
// 1. Check if the network request was actually successful
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
// 2. Verify the server actually returned JSON
const contentType = response.headers.get("content-type");
if (!contentType || !contentType.includes("application/json")) {
throw new TypeError("Oops, we haven't got JSON!");
}
const data = await response.json();
2. The Trailing Comma Dilemma (`Unexpected token } or ]`)
In modern programming languages like JavaScript (ES2017+), Python, and PHP, trailing commas at the end of object properties or array lists are widely encouraged. They make adding new lines easier and keep version control diffs clean.
However, the JSON specification strictly forbids trailing commas.
When a strict JSON parser encounters a comma, the state machine anticipates another key-value pair or array element. If it hits a closing brace (}) or bracket (]) instead, it throws a syntax exception.
{
"endpoint": "/users",
"limit": 50,
"active": true,
}
✔ Valid JSON:
{
"endpoint": "/users",
"limit": 50,
"active": true
}
The Debugging Fix
If your backend is generating JSON via string concatenation rather than a native serialization function (e.g., building JSON manually in a loop), you will likely leave a trailing comma on the final iteration. Always use native serialization libraries (like json.dumps() in Python or JSON.stringify() in JavaScript) rather than manually joining strings.
3. The Strict Quote Rule: Single Quotes and Unquoted Keys
JSON is not a 1-to-1 reflection of JavaScript objects. In JavaScript, you can use single quotes, double quotes, or backticks for strings, and you can leave object keys entirely unquoted.
JSON requires ASCII double quotes (") exclusively for both property keys and string values.
{ 'name': 'Alice' }is invalid due to single quotes.{ role: "Admin" }is invalid due to unquoted keys.{ "name": "Alice", "role": "Admin" }is structurally sound.
If you copy output directly from a Node.js console log or a Python dictionary print statement, it will often contain single quotes. Before parsing it, you must serialize it programmatically or run a controlled find-and-replace to enforce double quotes.
4. Escaping Control Characters and Raw Line Breaks
A JSON string must be a continuous sequence of characters enclosed in double quotes. If the string contains literal double quotes, raw line breaks (hitting "Enter" inside the string), or literal backslashes, the parser will fail.
- Unescaped Quotes:
{"quote": "She said "Hello""}fails because the parser interprets the second quote as the end of the string. You must escape it:{"quote": "She said \"Hello\""}. - Raw Line Breaks: Literal carriage returns inside a string value are illegal. They must be encoded as the explicit newline token:
\n. - Backslashes: File paths like
C:\Users\Adminmust be double-escaped toC:\\Users\\Admin.
5. Comments Inside JSON Payloads
Because developers frequently use JSON for configuration files, there is a strong temptation to leave annotations using // Single line or /* Block comment */.
Douglas Crockford, the creator of JSON, intentionally removed comments from the specification to prevent parsing engines from executing hidden directives. Standard JSON endpoints will reject any payload containing comments. If you must add notes to a strict JSON file, inject them as dummy data keys:
"_comment": "This value controls the timeout threshold",
"timeout": 30
}
6. How to Locate "Position X" in Massive JSON Files
When a Node.js runtime or browser console tells you Unexpected string in JSON at position 284512, finding that exact character index manually is nearly impossible—especially if the JSON is minified into a single continuous line.
To isolate the error quickly without risking your proprietary data on insecure third-party servers, use an in-browser client-side formatting tool:
- Copy your broken JSON payload.
- Paste it into a local, client-side formatting workspace.
- Attempt to format the data with 2-space indentation.
- The client-side parser will halt and highlight the exact line and column number where the syntax breaks, making it immediately visible for correction.
Once the error is fixed and validated, you can safely compress the payload back into a single line for production transmission.
Frequently Asked Questions
Can I send binary data, like images, inside JSON?
No. JSON is strictly a textual data format. To transport binary objects safely within a JSON payload, you must encode the binary stream into text first using Base64 encoding.
Why does my JSON parse correctly in the browser but fail on the server?
This is frequently caused by a UTF-8 Byte Order Mark (BOM). Some text editors invisibly prepend a zero-width character (\uFEFF) to the beginning of files. Browsers often ignore this silently, but strict backend parsers will throw a syntax error at position 0. Configure your text editor to save files as "UTF-8 without BOM."
Is NaN or Infinity valid in JSON?
No. JSON specification does not support NaN (Not-a-Number) or Infinity. If you serialize a JavaScript object containing these values, JSON.stringify() will convert them to null to prevent parsing exceptions.
How do I prevent 64-bit integer precision loss when parsing JSON?
Standard JavaScript parses all numbers as 64-bit floating-point values. Any integer larger than 9,007,199,254,740,991 will silently lose precision and be rounded. To avoid this, always format massive identifiers (like database primary keys) as strings (e.g., "id": "1152921504606846976") before sending them in JSON.
What is the difference between JSON and a JavaScript object?
JSON is purely a string-based text format used for data interchange across a network. A JavaScript object is a data structure actively residing in computer memory. You serialize an object to turn it into JSON text, and you parse JSON text to turn it into an object in memory.