catchjs

What causes SyntaxError on live web sites?

The SyntaxError is supposed to be obvious. It is the browser's mechanism to tell the programmer that they've written code that isn't syntactically valid. You've made a typo, and you fix it in 10 seconds. However, it turns out that when these errors happen on live websites, this is usually not the root cause.

We crawled the top 1 million domains on the web, noting statistics about the errors occurring on them. When we dig into the specific instances of SyntaxError, they usually don't look like errors directly written by a human. There is a different culprit that is much more common: The website links to a script, but the server responds with something unexpected, like an HTML page explaining the file cannot be found. Programmatically generated JavaScript is another common culprit. Below are some common variants of this error, along with common causes found during our crawl of the top 1M domains on the web.

This post is a result of our JavaScript Errors and Performance in the Wild 2020 study, where we crawled the top 1 million domains in order to learn about errors and performance on the web.
We do JavaScript error tracking for our customers. This time we decided to track errors on the entire web. In our crawl, the SyntaxError made up 8.8% of all errors found, occurring on 1.5% of all sites.

Unexpected token '<'

The JavaScript parser has encountered a '<' in a place it doesn't expect one. When this happens during development it's usually typo from the programmer, but on production websites it's usually caused by something else entirely: The site wants to load something it expects to be a script, but it is getting something else. For example:

SyntaxError: Unexpected token <

Here the site has linked a JavaScript file, but the server is responding with HTML content saying that file does not exist. The JavaScript parser boldly tries to interpret this HTML as JavaScript, but fails on the first character.

In Firefox, this error appears as expected expression, got '<'.

"Unexpected token" errors made up 52% of all SyntaxErrors in our crawl and 6.5% of all errors.

Unexpected identifier

Again, we usually see this when a linked script URL returns something that isn't actually a script. In this example, the server is producing an error message in text format, and the JavaScript parser has to give up some words in.

SyntaxError: Unexpected identifier

In Firefox, this error appears as unexpected token: identifier.

"Unexpected identifier" errors made up 10.9% of all SyntaxErrors in our crawl and occurred on 1.4% of all sites with errors.

Invalid or unexpected token

Sometimes programmers have mistakes in their code. Other times, programmers write a program to write a program that has mistakes in it. Programmatically generated JavaScript is another common cause of SyntaxErrors. In the following example, it seems clear what has happened.

SyntaxError: Invalid or unexpected token

Here the code has a newline character in the middle of a string literal, which produces a syntax error. A possible explanation is that the code contains something like write("gtag('config', '$identifier')" where the $identifier is a variable whose value comes, for example, from a database. If the $identifier value ends with a newline, we end up with broken JavaScript. Errors like these can indicate dangerous problems. If the value written into JavaScript comes from some users input, that user can inject any JavaScript into the site by changing that value, thereby taking over the site.

In Firefox, this error will get a more specific error message, for example: '' string literal contains an unescaped line break.

"Invalid or unexpected token" errors made up 16% of all SyntaxErrors in our crawl and occurred on 2% of all sites with errors.

Unexpected token < in JSON at position 0

This error occurs when the function JSON.parse() gets passed input that isn't proper JSON. The typical cause of this is that the input comes from a call to a Web API that has returned something other than what it was supposed to - like an HTML page with a 404 message.

SyntaxError: Unexpected token < in JSON at position 10

In Firefox, this error will tell you where in the string the parser gave up, for example: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data.

"Unexpected token in JSON" errors made up 4% of all SyntaxErrors in our crawl and occurred on 0.5% of all sites with errors.

Unexpected end of JSON input

This means JSON.parse() was passed something that was valid JSON up until the end, but it ended too soon. In practice it seems the most common situation is that the function was passed an empty string. Another reason would be if the input comes from a server that, for whatever reason, cut its response short.

In Firefox, this will show up similar to: JSON.parse: end of data while reading object contents at line 1 column 3 of the JSON data.

"Unexpected end of JSON input" errors made up 1.7% of all SyntaxErrors in our crawl and occurred on 0.2% of all sites with errors.

Unexpected end of input

This happens when linked JavaScript source code is cut short. It can occur if the web server for some reason cuts a response short (which it is not supposed to do), or because an incomplete file has been uploaded to the server. If it happens consistently, the latter option is more likely.

SyntaxError: Unexpected end of input

In Firefox, this will show up similar to: '' literal not terminated before end of script.

"Unexpected end of input" errors made up 5.5% of all SyntaxErrors in our crawl and occurred on 0.7% of all sites with errors.

missing ) after argument list

SyntaxError: missing ) after argument list

Unlike most of the others, this seems to not typically be caused by network resources containing the wrong data, but rather by actually wrong code. Programmatically generated JavaScript seems like a likely cause for many of these.

"missing ) after argument list" errors made up 6.3% of all SyntaxErrors in our crawl and occurred on 0.8% of all sites with errors.

Honorable mention: New JavaScript syntax in older browsers.

Another common problem is SyntaxErrors caused by new JavaScript syntax executed by older browsers that do not support it. Since our crawl executed web pages in a recent browser, this was not a common error in the crawl, but it is a common problem on live websites when they are visited by older browsers. The JavaScript language has gained a lot of new syntax in recent years, but the new syntax does not always have wide support among the browsers people use. For example, declaring an ES6 class may produce the error Unexpected token class. Using let and const in an older browser may show up as something like Block-scoped declarations (let, const, function, class) not yet supported outside strict mode.

These problems are particularly nefarious, since things might work perfectly in the developer's browser, while the product breaks for a portion of the users. Testing across a wide variety of browsers helps guard against this. It is also a good argument for enabling a JavaScript error logging service on the site (our favorite). It is also a good idea to look at browser compatibility tables like those on caniuse.com, and check that your selected language features have an acceptable coverage among browsers currently in use.

See also our articles on what causes ReferenceError and TypeError on live web sites.