Post Featured Image

TIL Thursday: Troubleshooting 'Uncaught SyntaxError: Unexpected token u in JSON at position 0'

This blog post is relevant for SuiteCommerce and all versions of SuiteCommerce Advanced.

A short one this week: I want to talk about an error message that a number of developers have asked me about over the years. On the face of it, it can be rather mysterious but once we take a look at it we'll see that it is actually a rather generic error that makes sense, and can be easily avoided.

Error Message

Let's start with how it looks. You may get the following error either in your web developer console, or, more likely, in NetSuite via the SSP application execution log:

Uncaught SyntaxError: Unexpected token u in JSON at position 0

Issue

Typically this occurs when you are working on a service file, where you are connecting to NetSuite and then requesting some data. When dealing with transmissions to and from the web store, data is usually in the form of an object. At various stages this data will be stringified (ie converted from an object to a string) or parsed (converted from a string to an object) and this will be where this error surfaces.

If you attempt to parse something other than an object, the JavaScript processor will usually fail. As it's expecting an object, it will stop at the exact point where it is failing, which is why it'll return the position where it got stuck. An unexpected token simply means that it was expecting data, but instead got a command keyword (but this error can be triggered by things like strings too because of how they're being told to be used).

If the unexpected token is a u and it is position 0 (ie the first thing) then that means it tried to parse something that begins with a u. And what familiar keyword in JavaScript begins with a u?

undefined

In other words, if you got the error message in the title of this post then the chances are you've told the JavaScript processor to run the following:

JSON.parse(undefined)

Try this out in your browser's developer console to see what I mean.

Resolving the Issue

So, we know what's happening. But why is it happening? Let's look at some of the possible causes.

Returning undefined

Now, you probably haven't told it to explicitly return undefined so that it can then attempt to parse it (why would you?) but the likelihood is that you have told your model, service or service controller to return a value to the frontend of your site but that value has not been successfully passed. You've done something like, "Return the value of variable foo" but have messed it up.

To check this, inspect (or log!) what you're returning:

  • Is it an object?
  • Does it have properties and have you called one that actually exists?
  • Do those properties have values?
  • Are there typos in your code, such as a misspelled name?

To illustrate this idea, see that trying to parse an object property that you have not defined will also return this error. For example:

var obj = {};
obj.foo;
> undefined

JSON.parse(obj.foo);
> Uncaught SyntaxError: Unexpected token u in JSON at position 0

If your code looks good, keep in mind that this could also happen if you've returned a variable before its value (an object) has been generated. In these cases, make sure any required operations have finished. For example, if your object will be generated after a promise has resolved, make sure it has been resolved before it is passed back. If the promise is failing, make sure it is set up to return an object that contains an error message!

Remember, if you're going to try and log an object to the SSP application log, you will need to stringify it first, otherwise you will just get [object Object] in the log.

Trying to Parse a String

The error message can also occur if you've passed back a string that the application then tries to parse as if it were an object. Consider an example where you try to parse a string that begins with the letter u:

JSON.parse('umbrella')
> Uncaught SyntaxError: Unexpected token u in JSON at position 0

Related Errors

There are a couple of other errors that look similar to this one.

Attempting to Parse Unstringified Data

Another important thing to keep in mind is that before JSON can be parsed it must first be stringified. Now, modern service controllers are set up to detect when 'complex' data is being sent, so it will automatically try to stringify an array or object that is being sent back. For whatever reason, this may not be happening so you will need to track down the specific part in your code and see what's going on.

Alternatively, you may be used to using service controllers and not realising that you need to do this operation manually if you're writing a custom .ss file, or if you're writing something like a Suitelet.

In other words, you may have sent your object back well-formed and correct, but it's not been stringified first, and the receiving part of the application has been told to parse the response. If it gets an unstringified object back, and it tries to parse it, it will fail.

To illustrate this, consider this example:

// Create my response object
var obj = {message: 'Hello!'}
obj.message
> "Hello!"

// Send the content back, eg:
// this.sendContent(obj)

// Receive the content and automatically attempt to parse it
JSON.parse(obj)
> Uncaught SyntaxError: Unexpected token o in JSON at position 1
// Note that the error is slightly different in content, but generally the same problem

// In reality, this is the shorthand for what should be happening
JSON.parse(JSON.stringify(obj))
> {message: "Hello!"}

Trying to Parse an HTML Document

In some cases, a full HTML error page is generated and that is sent back instead of the desired value. When this happens, you'll see something like this:

Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0

There is usually a very specific reason why this happened, that depends on your circumstances. Generally speaking, however: you've tried to request something, the server has failed, and, rather than return an object, it's generated a full HTML error page and sent that back. The reason why there's a < character at the start is because it's always the first character in a HTML page's source. In most cases, it will be <!DOCTYPE html>.

Therefore, if you want to troubleshoot this error, take a look at your browser's Network tab in the developer tools and see what page it is sending back to you. It will usually have an error message in the body of the HTML.

Bonus Tip: Using JSON Methods to Copy an Object

Finally, a fun tip that relates to JSON.parse() and JSON.stringify(): if you've ever wanted to deep copy an object such that an object's values are copied across to a new object by value rather than by reference, you can use JSON.parse(JSON.stringify(obj)), where obj is your object.

For the record, you should use our built-in _.deepCopy() method in almost all cases because we account for certain situations where deeply copying an object can be problematic (such as with a Backbone model).

Anyway, what stringifying and immediately parsing does is convert the object to a string, thereby converting the properties and resolved values of the entire object to a string (and therefore terminating their pointers' connections) and then converts it back to an object that you can use. This can be super helpful when you want to create a copy of an object as it is in that point in time:

// Create two objects, one which is a copy of it by reference
var obj1 = {message: 'Hello!'}
var obj2 = obj1

// Are they the same?
obj1.message == obj2.message
> true

// At the moment, they are linked by reference, so changing a value in one will change a value in another
obj2.message
> "Hello!"

obj1.message = 'Goodbye!'
obj2.message
> "Goodbye!"

// OK, but what we stringify and then parse one object's values and reassign it?
obj2 = JSON.parse(JSON.stringify(obj1))
obj2.message = 'Hello!'

// They are no longer identical! (This is very useful for large objects!)
obj1.message
> "Goodbye!"
obj2.message
> "Hello!"

From a performance perspective, it's actually pretty quick, and it certainly saves you the hassle of writing a loop.