← All articles

Unexpected Token u in JSON at Position 0: Fix JSON.parse(undefined)

Fix Unexpected token u in JSON at position 0 by finding the undefined value passed to JSON.parse(): missing props, localStorage mistakes, async state, no-return functions, env vars, and unsafe fallbacks.

SyntaxError: Unexpected token u in JSON at position 0 means JSON.parse() received undefined or the literal string "undefined" instead of JSON text. JavaScript converts the value undefined to the string "undefined" before parsing, and u is not a valid first character for JSON.

The fix is to find why the value is missing. Do not start by editing the JSON. There usually is no JSON yet. A variable was unset, a property path was wrong, async data was not ready, a function forgot to return, or a storage/config lookup used a fallback that produced undefined.

Quick Diagnosis

Log the value right before JSON.parse():

function inspectJsonParseInput(value) {
  const text = typeof value === "string" ? value : String(value);

  return {
    type: typeof value,
    isUndefined: value === undefined,
    isNull: value === null,
    length: typeof value === "string" ? value.length : null,
    preview: JSON.stringify(text.slice(0, 120))
  };
}

console.log(inspectJsonParseInput(input));

Then match the result:

What you see What probably happened First fix
type: "undefined" Missing variable, missing property, or no return value Trace the source before parsing.
preview: "undefined" The string "undefined" was stored or passed around Fix the writer; do not treat it as JSON.
type: "object", isNull: true The value is null JSON.parse(null) returns null; decide if that is acceptable.
length: 0 Empty string Handle as no input or debug as Unexpected end.
preview: "[object Object]" Object was coerced to a string Debug Unexpected token o.
preview: "<!DOCTYPE html" HTML response Debug Unexpected token <.

This is a source bug, not a formatting bug. A JSON repair tool can repair almost-JSON; it cannot guess an object that was never supplied.

Why undefined Becomes a SyntaxError

JSON.parse() does not type-check most inputs first. It converts the argument to a string, then parses that string as JSON.

JSON.parse(undefined);
// Same as JSON.parse("undefined")

The JSON grammar allows a document to start with:

  • { for an object
  • [ for an array
  • " for a string
  • t for true
  • f for false
  • n for null
  • a number character

It does not allow u, because JSON has no undefined value.

That is why these behave differently:

JSON.parse(undefined); // SyntaxError: Unexpected token u
JSON.parse("undefined"); // SyntaxError: Unexpected token u
JSON.parse(null); // null
JSON.parse("null"); // null
JSON.parse(""); // SyntaxError: Unexpected end of JSON input

null surprises people because it is converted to "null", and "null" is valid JSON. undefined converts to "undefined", and "undefined" is not valid JSON.

Cause 1: Wrong Property Path

The most common real bug is a property that does not exist:

const settings = {
  user: {
    preferencesJson: "{\"theme\":\"dark\"}"
  }
};

const raw = settings.user.preferenceJson;
const prefs = JSON.parse(raw);

The actual key is preferencesJson, but the code reads preferenceJson. Missing object properties evaluate to undefined, so the parser sees "undefined".

Fix it by checking the source object, not by wrapping parse errors:

const raw = settings.user.preferencesJson;

if (typeof raw !== "string") {
  throw new TypeError("settings.user.preferencesJson must be a JSON string");
}

const prefs = JSON.parse(raw);

For nested data from third-party APIs, log the shape once with a tree viewer or a safe preview before guessing at property names.

Cause 2: Parsing Before Async Data Arrives

In front-end code, state often starts as undefined and becomes a string later.

let settingsJson;

loadSettings().then((value) => {
  settingsJson = value;
});

const settings = JSON.parse(settingsJson);

The parse runs before the promise resolves.

Fix the timing:

const settingsJson = await loadSettings();
const settings = JSON.parse(settingsJson);

In React, avoid parsing optional props or state during the initial loading render:

function SettingsPanel({ settingsJson }) {
  if (typeof settingsJson !== "string") {
    return null;
  }

  const settings = JSON.parse(settingsJson);
  return settings.theme;
}

For repeated renders, memoize after the value exists:

function parseSettings(settingsJson) {
  if (typeof settingsJson !== "string" || !settingsJson.trim()) {
    return { theme: "system" };
  }

  return JSON.parse(settingsJson);
}

The parser is only where the bug surfaces. The real bug is usually a loading state that is not modeled explicitly.

Cause 3: localStorage and sessionStorage Confusion

localStorage.getItem("missing") returns null, not undefined.

const raw = localStorage.getItem("settings");
JSON.parse(raw); // returns null if the key is missing

So if you see token u, the code often did one of these instead:

JSON.parse(localStorage.settings);
JSON.parse(window.localStorage["settings"]);

Property access on localStorage can return undefined when the key does not exist. Use getItem() and handle null deliberately:

function readStoredJson(key, fallback = null) {
  const raw = localStorage.getItem(key);

  if (raw === null) {
    return fallback;
  }

  if (!raw.trim()) {
    return fallback;
  }

  return JSON.parse(raw);
}

Also check the write path. If previous code stored the literal string "undefined", parsing it later fails the same way:

localStorage.setItem("settings", String(undefined));

Do not store "undefined" as a placeholder. Remove the key or store valid JSON:

localStorage.removeItem("settings");
localStorage.setItem("settings", JSON.stringify({ theme: "dark" }));

Cause 4: A Function Forgot to Return

Functions with no return produce undefined.

function loadConfigJson() {
  const raw = "{\"debug\":true}";
}

const config = JSON.parse(loadConfigJson());

Fix the return:

function loadConfigJson() {
  return "{\"debug\":true}";
}

const config = JSON.parse(loadConfigJson());

This happens in callbacks too:

const raw = items.find((item) => {
  item.id === "settings";
});

The callback block forgot return, so find() returns undefined even when the item exists.

const match = items.find((item) => item.id === "settings");
const settings = match ? JSON.parse(match.value) : null;

When the value is produced by a helper, test the helper separately. Do not let parse errors hide a no-return bug.

Cause 5: Environment Variables and Optional Config

Environment variables are strings when present and undefined when missing.

const flags = JSON.parse(process.env.FEATURE_FLAGS_JSON);

That line is fine only if the variable is required and always set. Otherwise, guard it:

function parseJsonEnv(name, fallback) {
  const raw = process.env[name];

  if (typeof raw !== "string" || !raw.trim()) {
    return fallback;
  }

  return JSON.parse(raw);
}

const flags = parseJsonEnv("FEATURE_FLAGS_JSON", {});

For required configuration, fail loudly at startup:

function requireJsonEnv(name) {
  const raw = process.env[name];

  if (typeof raw !== "string" || !raw.trim()) {
    throw new Error(`Missing required env var: ${name}`);
  }

  return JSON.parse(raw);
}

Use a fallback only when absence is valid. For secrets, permissions, billing config, and feature gates, a silent {} fallback may be worse than a crash.

Cause 6: Optional Function Arguments

Helpers often start simple and then get called with missing arguments:

function parseUser(rawUserJson) {
  return JSON.parse(rawUserJson);
}

parseUser();

Make the contract explicit:

function parseRequiredJson(raw, label = "value") {
  if (typeof raw !== "string") {
    throw new TypeError(`${label} must be a JSON string`);
  }

  return JSON.parse(raw);
}

function parseOptionalJson(raw, fallback = null) {
  if (typeof raw !== "string" || !raw.trim()) {
    return fallback;
  }

  return JSON.parse(raw);
}

Use parseRequiredJson() when missing input means the caller is wrong. Use parseOptionalJson() when missing input is expected, such as an optional text field or a cache miss.

Cause 7: Fetch Helpers That Return undefined

Sometimes the fetch call is not the problem. Your wrapper is.

async function getUserJson() {
  const response = await fetch("/api/user");

  if (!response.ok) {
    return;
  }

  return response.text();
}

const raw = await getUserJson();
const user = JSON.parse(raw);

On non-OK responses, getUserJson() returns undefined. The caller then blames JSON.parse().

Return a structured result instead:

async function getUserJson() {
  const response = await fetch("/api/user");
  const text = await response.text();

  if (!response.ok) {
    return { ok: false, status: response.status, text };
  }

  return { ok: true, status: response.status, text };
}

const result = await getUserJson();

if (!result.ok) {
  throw new Error(`HTTP ${result.status}`);
}

const user = JSON.parse(result.text);

Returning undefined as an error signal is cheap at first and expensive later.

What Not to Do

Do not hide this error with a broad catch unless missing input is truly acceptable:

function unsafeParse(raw) {
  try {
    return JSON.parse(raw);
  } catch {
    return {};
  }
}

That turns configuration bugs into mysterious default behavior.

Prefer a helper that records why it fell back:

function parseJsonWithFallback(raw, fallback, label) {
  if (typeof raw !== "string" || !raw.trim()) {
    console.warn(`${label} was missing; using fallback`);
    return fallback;
  }

  return JSON.parse(raw);
}

In production logs, record type, key name, and length. Avoid logging full values when they may contain tokens, cookies, customer data, or private config.

Can JSON Fix Repair It?

If the input is undefined, there is nothing to repair. The value is absent.

JSON Fix can help if you have actual text that is almost JSON: single quotes, trailing commas, unquoted keys, comments, Python True, or a missing closing bracket. It cannot infer a missing settings object from the word undefined.

If you have a suspicious string, paste it into JSON Validator or JSON Fix. If the input is not a string at all, debug the JavaScript value first.

Frequently Asked Questions

What does "Unexpected token u in JSON at position 0" mean?

It means JSON.parse() received undefined or the string "undefined". JavaScript converts undefined to "undefined" before parsing, and u is not a valid first character for JSON.

Why does JSON.parse(undefined) throw a SyntaxError?

Because JSON.parse() converts its argument to a string before parsing. The parser receives "undefined", then rejects the leading u according to the JSON grammar.

Why does JSON.parse(null) not throw?

null is converted to the string "null", and "null" is valid JSON. It parses to JavaScript null. Missing localStorage keys usually return null, not undefined, when read with getItem().

Is an empty string the same problem?

No. JSON.parse("") and JSON.parse(" ") usually throw Unexpected end of JSON input, because the parser receives no JSON value at all. Token u points specifically to undefined or "undefined".

How do I fix this with localStorage?

Use localStorage.getItem(key), handle null as a missing key, and only parse non-empty strings. When writing, store JSON.stringify(value) or remove the key; do not store the literal string "undefined".

How do I fix this in React or async code?

Do not parse until the value exists. Model the loading state, check typeof value === "string", and parse after the promise, prop, or state value has arrived.

Can a JSON repair tool fix undefined?

Not if the JavaScript value is actually undefined. A repair tool needs text to repair. If the text is the literal word "undefined", the correct fix is usually to find why that placeholder was written.

How do I prevent this in production?

Parse only strings, use explicit required-vs-optional helpers, return structured errors from fetch wrappers, validate environment config at startup, and log safe metadata such as type, key name, and length before handling parse failures.

Related Tools & Guides

Sources

Last reviewed July 2026.