SyntaxError: Unexpected token, explained and fixed

This is a parse error, not a runtime error: the JavaScript engine read the file, reached a character or word it could not fit into the grammar at that spot, and stopped before running anything. The message names the offending token and usually a position. Most cases are a genuine typo near that spot, but one famous variant has nothing wrong with the code at all: the file being parsed is not JavaScript, it is an HTML error page or a JSON document fed to the wrong parser.

How to find it

  1. Start at the reported position (line and column, or the character offset) and read a few lines above it. The parser often travels past the real mistake, an unclosed bracket or string earlier, before it gives up, so the named token is where it noticed, not always where it broke.
  2. Check the brackets: count opening and closing { } ( ) [ ] in the function or object around the spot. An editor's bracket-matching (click a bracket, its partner highlights) finds the imbalance quickly.
  3. Check what the file actually contains. If the token is < and the code looks fine, the “JavaScript” being parsed is probably an HTML page, typically a 404 or login page a server returned for a script or JSON request.

The usual causes

  1. Unbalanced or extra punctuation: a missing comma in an object or array, an extra closing brace copied with a block, a stray semicolon inside an expression.
  2. An unterminated string or template literal swallowing the lines after it, so the parser meets code while still inside a string.
  3. JSON handled as JavaScript or the reverse: Unexpected token '<' after a fetch means the response was HTML, not JSON. Unexpected token ':' often means JSON text was evaluated as code.
  4. Newer syntax in an older engine or a plain script: optional chaining in an ancient browser, or TypeScript type annotations and decorators in a file that was never transpiled.
  5. Invisible damage from copying: smart quotes pasted from a document, a non-breaking space, or an encoding artifact at the reported position.

The fixes, in order

  1. Fix the punctuation at the real break point, which bracket counting and a formatter reveal. Running the file through a formatter (Prettier or the editor's format command) fails loudly at the exact region that does not parse.
  2. If the token is <, inspect the network response, not the code. Log response.status and the first characters of the body before parsing, and fix the URL or the server route that returned a page instead of data.
  3. Parse JSON with the JSON parser: JSON.parse(text) or response.json(), never eval or a script tag, and validate untrusted JSON separately if it came from a file.
  4. Match the syntax to the pipeline: run TypeScript and modern syntax through the project's transpiler/bundler, and check the file extension and build config if plain Node or a browser is parsing it raw.

Common questions

Why does the error point at a line that looks correct? The parser reports where it became impossible to continue, which can be several tokens after an unclosed string, comment, or bracket. Inspect upward from the reported position for the first construct that never closes.

What does “Unexpected token '<', "..." is not valid JSON” mean? A fetch expected JSON and received an HTML page instead, usually a 404, a redirect to a login page, or a server error page. The bug is in the request or the server, not in the JSON handling.

Can an invisible character really cause this? Yes. Curly quotes and non-breaking spaces pasted from documents or web pages are not valid JavaScript punctuation and produce exactly this error at that character.

Related errors

SyntaxError: Unexpected end of input · ReferenceError: is not defined · Cannot read properties of undefined