← 記事一覧

JSON の位置 0 で Unexpected Token u: undefined をパース

"Unexpected token u" エラーは JSON.parse(undefined) を呼んだことを意味します。なぜ undefined が "undefined" になるか、どう防ぐか、安全パースのヘルパーを学びます。

SyntaxError: Unexpected token 'u', "undefined" is not valid JSON(古いエンジン:Unexpected token u in JSON at position 0)はほぼ常に JSON.parse(undefined) を呼んだことを意味します。JavaScript は undefined をテキスト "undefined" に文字列化し、パーサは先頭の u で詰まります。理由と直し方は以下の通り。

エラーの見た目

// V8 (Chrome / Node / Edge)
SyntaxError: "undefined" is not valid JSON
SyntaxError: Unexpected token 'u', "undefined" is not valid JSON
SyntaxError: Unexpected token u in JSON at position 0   // 古い V8

// Firefox
SyntaxError: JSON.parse: unexpected character at line 1 column 1

// Safari
SyntaxError: JSON Parse error: Unexpected identifier "undefined"

位置 0 の u は文字列 "undefined" の最初の文字 —— パーサは実データを受け取らなかったのです。

なぜ起こるか:undefined をパースした

JSON.parse() は引数をまず文字列に強制します。undefined を渡すと、リテラル文字列 "undefined" をパースしますが、これは有効な JSON ではありません。値が undefined になる典型的な理由:

  • 変数や関数引数が一度も代入されていない
  • オブジェクトのプロパティが存在しない(タイポや構造違い):obj.missing
  • async な値がまだ準備できていない(await の前にパースした)
  • return のない関数をソースとして使った

壊れた例

const cached = localStorage.getItem('settings'); // キー欠落 → null、OK
const draft  = window.appState?.draft;            // プロパティ欠落 → undefined
const data   = JSON.parse(draft);                 // ❌ "undefined" is not valid JSON

修正例

// パース前にガード
const data = draft ? JSON.parse(draft) : null;

// または安全なヘルパ
function safeParse(text, fallback = null) {
  if (typeof text !== 'string' || text.trim() === '') return fallback;
  try { return JSON.parse(text); } catch { return fallback; }
}
const data2 = safeParse(draft);

注意:JSON.parse(null)投げません —— null を返します。そして localStorage.getItem() は欠落キーに対して nullundefined ではなく)を返します。なので u エラーは undefined の値を指す、ストレージのキー欠落ではない。

SyntaxError vs TypeError:なぜ こちら になるか

細かいが有用な点:JSON.parse(undefined)SyntaxError を投げます。TypeError ではありません。なぜ?仕様では JSON.parse はまず引数を 文字列に強制"undefined")し、その文字列をパースするから。エラーは「この文字列は有効な JSON でない」であって「型が違う」ではない。だから JSON.parse(undefined)JSON.parse("undefined") は同じ「position 0」メッセージを出すのです。

対照的に型チェックを 行う API:JSON.stringify(BigInt(1))TypeErrorJSON.parse(Symbol())TypeError(Symbol は文字列化できない)。パースエラーを捕まえるなら err instanceof SyntaxError で絞り込み、悪いデータ悪い引数 を分けて扱う。

直し方 —— ステップごとに

  1. 入力をログする:console.log(typeof src, src) をパース直前に。undefined と出れば犯人。
  2. セットされるはずの場所を辿る —— 未初期化の state フィールド、欠けた引数、またはオブジェクトに存在しないプロパティ。
  3. ガードを追加if (src))または safeParse フォールバックで、欠落した値が JSON.parse() に届かないようにする。
  4. async の場合、パース前に値を await することを確認。

よくある質問

「Unexpected token u in JSON at position 0」はどういう意味?

undefinedJSON.parse() に渡しました。文字列 "undefined" になり、先頭の u は妥当な JSON の開始文字ではありません。

「token o」や「token <」エラーと同じ?

同じファミリー、別の値。u = undefinedtoken o = オブジェクトが [object Object] に文字列化された;token < = HTML レスポンス。名前の文字が実際に渡されたものを教えてくれます。

なぜ JSON.parse(null) は同じエラーを投げない?

"null" は妥当な JSON なので JSON.parse(null)null を返します。undefined(→ "undefined")だけが u エラーを引き起こします。

今すぐ直す