Unexpected Token in JSON: The 10 Real Causes and How to Fix Each
A troubleshooting guide for JSON parse errors such as Unexpected token, Unexpected end of JSON input and Bad control character, with the exact cause behind each message.
Published September 28, 2026 · By Sudip Bhowmick
Few error messages are as unhelpful as Unexpected token < in JSON at position 0. It tells you where parsing stopped, not why. The good news is that JSON is a small, strict format, so the list of things that can go wrong is short. Work through these ten causes in order and you will find the problem in nearly every case.
Start By Reading the Position
The error position is a character offset. Position 0 means the very first character is wrong, which points to something other than JSON arriving at all. A position near the end usually means truncation. A position in the middle points to a syntax mistake at that exact spot. Paste the text into a formatter that reports line and column, which is much easier to act on than a raw offset.
The Ten Causes
- ▸1. The response is HTML, not JSON. An error page, a login redirect or a proxy message starts with an angle bracket. That is the classic Unexpected token < at position 0. Log the raw body and the HTTP status before you parse.
- ▸2. A trailing comma. JSON forbids a comma after the last item in an object or array, although JavaScript allows it.
- ▸3. Single quotes. JSON strings and keys must use double quotes.
- ▸4. Unquoted keys. A key such as name without quotes is valid JavaScript but not valid JSON.
- ▸5. Comments. JSON has no comments. Configuration formats that allow them, such as JSONC or JSON5, need their own parsers.
- ▸6. Invalid values: undefined, NaN, Infinity and functions are not JSON. Serializers drop or convert them, but hand written JSON containing them fails.
- ▸7. Unescaped control characters. A real line break or tab inside a string must be written as a backslash n or a backslash t. This shows up as Bad control character in string literal.
- ▸8. Truncated data. Unexpected end of JSON input means the text stops before the structure is closed, which happens with cut off responses, partially written files and unclosed brackets.
- ▸9. A byte order mark or stray characters at the start. A BOM at position 0 is invisible but is not whitespace to many parsers. Strip it before parsing.
- ▸10. Numbers JSON does not allow: leading zeros such as 007, a plus sign, hexadecimal values and a trailing decimal point.
A Debugging Routine That Works
- ▸Print the exact string that reaches the parser, with its length, before anything else touches it.
- ▸Check the Content-Type and status code. A 200 with text/html is a different bug from a 500 with JSON.
- ▸Look at the first and last 100 characters. Many problems are visible at the edges.
- ▸Run the text through a validator that gives a line and column and fix the first error only. One mistake often causes several later error messages.
- ▸If the data is machine generated, find the code that built it. Hand written serialization with string concatenation is the usual source of broken JSON.
Special Case: Double Encoded JSON
If the text starts and ends with a quotation mark and every inner quote is preceded by a backslash, the JSON was turned into a string and then stringified again. Parse it once to get the inner string, then parse that string. The JSON Unstringifier tool automates this and unwraps several layers.
Prevent Parse Errors in the First Place
- ▸Always generate JSON with a serializer, never with string concatenation or template strings.
- ▸Set the Content-Type header to application/json and handle non-JSON responses before parsing.
- ▸Validate configuration files in CI so a typo never reaches production.
- ▸Prefer a format with comments, such as YAML or TOML, for files that humans edit often, and keep JSON for data exchange.
Conclusion
Unexpected token errors usually come from one of ten causes: HTML where JSON was expected, trailing commas, single quotes, unquoted keys, comments, invalid values, raw control characters, truncation, a byte order mark or a number format JSON rejects. Read the position, inspect the raw text, fix the first problem and let a serializer produce the data so the error cannot come back.
Free Tool
Open the JSON Formatter and Validator