Unhandled Rejection (SyntaxError): Unexpected token < in JSON at position 0
You made an HTTP request, probably with Fetch, and it blew up with this error. Or a very similar one.
Ugh.
Here’s what causes it and how to fix it.
Read on for a quick suggestion, and watch the video for a walkthrough of a few techniques you can try to debug this in your own app.
The Cause
This happens when you make a request to the server and parse the response as JSON, but it’s not JSON. The code responsible might look something like this:
fetch('/users').then(res => res.json())
The actual request worked fine. It got a response. But the res.json()
is what failed.
JSON.parse
You might instead be parsing the JSON yourself with JSON.parse
like this:
JSON.parse(theStringThatIsNotJson);
JSON.parse
is what fetch’s res.json()
is doing under the hood, so the error will be the same either way.
Valid JSON
JSON should start with a valid JSON value – an object, array, string, number, or false
/true
/null
. This response started with a <
(hence the “Unexpected token <”).
That unexpected token, <
, is a strong clue that the response was HTML instead of JSON.
The root cause is that the server returned HTML or some other non-JSON string. Why would it do that?
“Unexpected token o in JSON at position 1” and other varieties
The exact text of this error will differ depending on what the server returned. The token and the position may vary, but the root cause is the same: the text that your app is trying to parse as JSON is not actually valid JSON.
Here are some other variations I’ve seen…
- Unexpected token < in JSON at position 1
- Unexpected token p in JSON at position 0
- Unexpected token d in JSON at position 0
Watch the video above for how this error works, and how to use your browser’s developer tools to figure out exactly what’s causing it. (or keep on readin’)
The Fix
The first thing to do is try logging it out. With fetch, you can use res.text()
instead of res.json()
to get the text string itself. Alter your code to read something like this, and check the console to see what’s causing the problem:
fetch('/users')
// .then(res => res.json()) // comment this out for now
.then(res => res.text()) // convert to plain text
.then(text => console.log(text)) // then log it out
Note that these res.json()
and res.text()
functions are asynchronous, so you cannot log their return value directly. That’s why the console.log must be in a separate .then
block.
Fix JSON.parse Unexpected Token
If you’re using JSON.parse directly, that’s a plain old synchronous call and you can replace the call with a console.log to see what’s going on.
// JSON.parse(someString) // comment this out temporarily
console.log(someString) // log out out, and see what's wrong
Blame the Server?
The server might return HTML instead of JSON for a bunch of reasons:
- The URL doesn’t exist and the server returned an 404 page as HTML. You might have a typo in the client code (
/users
instead of/user
) or in the server code that sets up the route. - The server might need a restart if you just added a URL to it. If you’re using an Express server for instance, and you just added a new
app.get('/users', ...)
route, but didn’t restart the server, then it doesn’t know about the new route yet. - The client’s proxy isn’t set up: if you’re using a Webpack dev server like Create React App, you can set up a proxy to forward requests to a backend server.
- The API root URL is
/
: If you’re using a proxy through Webpack or Create React App, make sure your API route is not at the root level/
. That’ll confuse the proxy and you’ll get back HTML instead of your API request. Instead, prefix the route with something like/api/
.
Also, check the browser devtools Network tab and look for the request that caused this error, and then look at the response that came back.
Is it a 404 page? (might be a missing route or a typo)
Is it the index.html page? (might be a missing route or a misconfigured proxy)
If everything looks fine, then restart your backend server and your frontend dev server, and see if the problem goes away.
Problem Solved?
Hopefully you’ve now gotten rid of the error. If not, leave a comment below with what you tried.