SyntaxError: Unexpected token in JSON
Nine times out of ten this means the response was HTML, not JSON: the '<' is the first character of <!DOCTYPE html> or an error page. Log the raw text before you call JSON.parse() — if it starts with '<', fix the URL, auth, or 500 so the server returns real JSON.
What the error means
JSON.parse() found a character that cannot start a JSON value at that position. "Unexpected token '<', \"<!DOCTYPE\"..." is the classic case: your fetch got an HTML page (a login redirect, a 404, or a 500 stack trace) and you tried to parse it as JSON.
The five causes, in order of frequency
1. HTML instead of JSON (token '<'). Check response.status and response.headers.get('content-type'). Print the first 200 characters of the body — you will usually see <!DOCTYPE html>.
2. Single quotes (token '\''): JSON needs double quotes — 'user' must be "user".
3. Trailing comma (token '}' or ']'): remove the comma after the last item.
4. Unquoted key: every key is a quoted string, so roles: becomes "roles":.
5. Leading BOM or junk: a byte-order mark or stray text before the first { trips the parser at position 0.
Fix it fast
Paste the payload into the tool above and hit Repair — it fixes single quotes, trailing commas, unquoted keys and Python literals. If the input is HTML, there is nothing to repair: the bug is upstream, in the request that returned a web page instead of data.
FAQ
Why does it always say "position 0"?
Because the very first character is wrong — almost always a '<' from an HTML response. The parser fails on the first token it reads.
How do I see what the server actually returned?
Log the raw text before parsing: const t = await res.text(); console.log(t.slice(0,200)); then JSON.parse(t). If it starts with '<', you received HTML.
Why does my code work in Postman but not in the app?
Postman hits the API directly; your app may be sending the request to the wrong URL or without auth, getting an HTML login or error page back.