"undefined" is not valid JSON

Something converted the value undefined to the six-character string "undefined" and handed that to JSON.parse. JSON has no undefined literal — the absent value in JSON is null.

How the message appears

The same fault, worded by different engines. V8 (Chrome, Node, Edge) changed its format around Chrome 109, so older and newer runtimes disagree about the same document.

  • SyntaxError: "undefined" is not valid JSON
  • SyntaxError: Unexpected token u in JSON at position 0
  • SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data

What causes it

localStorage

By far the most common source. localStorage.setItem("k", undefined) stores the *string* "undefined", and JSON.parse(localStorage.getItem("k")) then throws. Note that a missing key returns null, and JSON.parse(null) quietly returns null instead of throwing — so the two failure modes look nothing alike.

A function with no return value

A code path that falls off the end returns undefined. Interpolated into a template literal it becomes "undefined" and travels onward as text.

JSON.stringify of undefined

JSON.stringify(undefined) returns undefined — the value, not a string. Write that to a file or a cache and the next reader gets "undefined" back.

The fix

Fix the writer, not the reader. Store null for an absent value, and guard the read: const raw = localStorage.getItem("k"); const value = raw && raw !== "undefined" ? JSON.parse(raw) : null;

Fails to parse
undefined
Parses
null

The example travels in the URL fragment, which browsers never send to a server.

Worth knowing

  • The older Unexpected token u in JSON at position 0 says the same thing: u is the first character of undefined.
  • JSON.parse(undefined) coerces its argument to the string "undefined" first, so passing the value and passing the string fail identically.

No cookies, no accounts, no tracking. Your JSON and text are processed entirely in your browser and never sent anywhere. We count anonymous page views (the page address only, nothing about you or your device), and use localStorage to remember your theme.