JSON.parse "Unexpected token o" and "undefined is not valid JSON": Fix
· 4 min read
Unexpected token o in JSON at position 1 means you passed an object, not a string, to JSON.parse: JavaScript turned it into the text [object Object], and the o after the [ is where parsing fails. Unexpected token u in JSON at position 0 (now "undefined" is not valid JSON) means the value was undefined. In both cases there is nothing wrong with your JSON; remove the extra JSON.parse or find out why the value is missing. To confirm a string really is JSON, paste it into the JSON validator.
JSON.parse converts its argument to a string before parsing. That rule explains every message on this page, and why JSON.parse(null) and JSON.parse(42) succeed while objects and undefined fail.
Minimal reproduction
const user = { name: "Ada" };
JSON.parse(user); // String(user) is "[object Object]"
let payload;
JSON.parse(payload); // String(undefined) is "undefined"
JSON.parse(null); // fine: "null" is valid JSON, returns null
JSON.parse(42); // fine: "42" is valid JSON, returns 42Every wording of the two errors
| Runtime | Parsing an object | Parsing undefined |
|---|---|---|
| Chrome 110+, Node 20+ | Unexpected token 'o', "[object Obj"... is not valid JSON | "undefined" is not valid JSON |
| Chrome and Node 18 and earlier | Unexpected token o in JSON at position 1 | Unexpected token u in JSON at position 0 |
| Firefox | JSON.parse: unexpected character at line 1 column 2 of the JSON data | JSON.parse: unexpected character at line 1 column 1 of the JSON data |
| Safari, Bun | JSON Parse error: Unexpected identifier "object" | JSON Parse error: Unexpected identifier "undefined" |
Unexpected token o: parsing data that is already parsed
This is the most common way to hit it: a library already converted the JSON for you, and the code parses it a second time.
await res.json()withfetchalready returns an object. Do not callJSON.parseon the result.- axios parses JSON responses automatically;
response.datais an object. - jQuery
$.getJSONand$.ajaxwithdataType: "json"pass a parsed object to the callback. - Express with
express.json()gives you a parsedreq.body. - A function that sometimes receives a string and sometimes an object, for example a message from
postMessageor a WebSocket wrapper that already decodes JSON.
// Wrong: parsing twice
const res = await fetch("/api/user");
const user = JSON.parse(await res.json()); // SyntaxError
// Right
const user2 = await res.json();If one code path really can receive either form, check the type instead of guessing:
function asObject(value) {
return typeof value === "string" ? JSON.parse(value) : value;
}If you see [object Object] inside your stored data or logs, the bug is upstream: something wrote String(obj) instead of JSON.stringify(obj), for example localStorage.setItem("user", user). That string is lost data; fix the writer, then clear the stored value.
undefined is not valid JSON: the value never arrived
undefined is a JavaScript value, not a JSON one, so this error always means the variable was empty when you parsed it. Typical sources:
- A misspelled or missing property:
JSON.parse(data.paylaod)or a field the API stopped sending. - Reading a value before an async call finished, such as React state on the first render.
- An environment variable that is not set:
JSON.parse(process.env.CONFIG)in a deployment whereCONFIGis missing. - A function that forgot to
returnits JSON string. - A cookie or query parameter that is absent on the first visit.
const raw = process.env.FEATURE_FLAGS;
if (raw === undefined) {
throw new Error("FEATURE_FLAGS is not set"); // a clear message beats a SyntaxError
}
const flags = JSON.parse(raw);localStorage.getItem is the exception people expect to fail: it returns null for a missing key, and JSON.parse(null) returns null without throwing, so the error shows up later as Cannot read properties of null. An empty string, on the other hand, throws a different error; see Unexpected end of JSON input.
Other single-letter tokens at position 0
| Token | What you parsed | Read |
|---|---|---|
< | An HTML page | DOCTYPE is not valid JSON |
N | NaN, or Python None | Python dict to JSON |
T / F | Python True / False | Python dict to JSON |
' | A single-quoted string | Unexpected token in JSON |
| Any letter | Plain text, such as an error message from the server | Log the raw text |
A safe pattern for unknown input
function parseMaybeJson(value) {
if (value === undefined || value === null || value === "") return null;
if (typeof value !== "string") return value; // already parsed
return JSON.parse(value); // let real syntax errors surface
}Once you have the object, the JSON viewer is a quick way to inspect its shape and confirm the field you expected is there. For every other parse error, start from the common JSON errors hub.
FAQ
Why does JSON.parse say "Unexpected token o in JSON at position 1"?
You passed an object instead of a string. JSON.parse converts it to [object Object], which fails at the o in position 1. The data is usually already parsed, for example by res.json() or axios.
What does "undefined" is not valid JSON mean?
The value passed to JSON.parse was undefined. Older Chrome and Node versions report it as Unexpected token u in JSON at position 0. Check the variable, property name or environment variable you are parsing.
Why does JSON.parse([object Object]) fail?
[object Object] is the default text form of a JavaScript object, not JSON. Use JSON.stringify(obj) to turn an object into JSON, and only call JSON.parse on strings.
Does JSON.parse(null) throw an error?
No. null becomes the string "null", which is valid JSON, so it returns null. That is why a missing localStorage key fails later instead of at the parse.

