Skip to content
Tools

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 42

Every wording of the two errors

All are SyntaxError. An array of objects gives the same message as a single object, because String([{}]) is also "[object Object]".
RuntimeParsing an objectParsing undefined
Chrome 110+, Node 20+Unexpected token 'o', "[object Obj"... is not valid JSON"undefined" is not valid JSON
Chrome and Node 18 and earlierUnexpected token o in JSON at position 1Unexpected token u in JSON at position 0
FirefoxJSON.parse: unexpected character at line 1 column 2 of the JSON dataJSON.parse: unexpected character at line 1 column 1 of the JSON data
Safari, BunJSON 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() with fetch already returns an object. Do not call JSON.parse on the result.
  • axios parses JSON responses automatically; response.data is an object.
  • jQuery $.getJSON and $.ajax with dataType: "json" pass a parsed object to the callback.
  • Express with express.json() gives you a parsed req.body.
  • A function that sometimes receives a string and sometimes an object, for example a message from postMessage or 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 where CONFIG is missing.
  • A function that forgot to return its 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

TokenWhat you parsedRead
<An HTML pageDOCTYPE is not valid JSON
NNaN, or Python NonePython dict to JSON
T / FPython True / FalsePython dict to JSON
'A single-quoted stringUnexpected token in JSON
Any letterPlain text, such as an error message from the serverLog the raw text

A safe pattern for unknown input

Handles the three non-errors explicitly and still throws for genuinely broken JSON.
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.

More JSON guides