"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

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.

What causes it

localStorage

By far the most common source. localStorage.setItem("k", undefined) stores the six-character 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.

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.

Written by Vishnu Shankar.

Your JSON and text are processed entirely in your browser and are never sent anywhere. To understand how the site is used we record each page view (the page, the referrer and an approximate location from your IP address) and keep it for 90 days. Nothing is stored on your device unless you choose it. Accept to also store a device identifier here and record your browser and device characteristics, which is what lets a return visit be told from a new one. Decline and nothing is sent at all. We respect Do Not Track. See our privacy policy.