SyntaxError: Unexpected token

構文として読めなかったときに出ます。エラーの位置は壊れた場所ではなく気づいた場所です。 JSON.parse で出る場合が特に多く、その見分け方と直し方までまとめています。

実行して検証済み処理系Node 22.22.3難易度●●○○○目安9更新

そこまで読んだところで、続きが構文として成り立たなくなったときに出ます。

javascript
const class = 1;
SyntaxError: Unexpected token 'class'
javascript
const o = { a: 1 b: 2 };

console.log(o);
SyntaxError: Unexpected identifier 'b'

ほかのエラーと違い、1行も実行されません。 読み込む段階で止まります。 だから console.log() を仕込んでも何も出ません

エラーの位置は「気づいた場所」

壊れている場所とは限りません。 ここを取り違えると、正しい行をいくら見ても直りません。

javascript
console.log('a'
SyntaxError: missing ) after argument list
javascript
console.log(JSON.parse("{'a':1}"));
SyntaxError: Expected property name or '}' in JSON at position 1 (line 1 column 2)

b は悪くありません。1 の後ろにカンマが無いのが原因です。 処理系は b まで読んで初めて「おかしい」と気づきました。

エラーが指す位置の1つ手前を見てください。

エラーが指すもの 実際に見る場所
Unexpected identifier 'b' b手前(カンマ・演算子の抜け)
Unexpected token ')' 対応する ( の中身
Unexpected end of input どこかの閉じ忘れ(ファイル末尾まで読み切った)

原因1: 括弧や引用符の閉じ忘れ

javascript
console.log(JSON.parse('{"a":1,}'));
SyntaxError: Expected double-quoted property name in JSON at position 7 (line 1 column 8)
javascript
console.log(JSON.parse(''));
SyntaxError: Unexpected end of JSON input

閉じ忘れは、そこではなくずっと後ろで気づかれます。 ファイルの最後まで読み切ってしまうと Unexpected end of input になります。

エディタの対応括弧の色分けを使ってください。 目で数えるより速く確実です。

原因2: JSON.parse に JSON でないものを渡した

実務でいちばん多いのがこれです。 同じ SyntaxError ですが、原因が全く違います。

javascript
console.log(JSON.parse('<!DOCTYPE html>'));
SyntaxError: Unexpected token '<', "<!DOCTYPE html>" is not valid JSON
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
OK | 解析できた NG | Unexpected token '<', "<!DOCTYPE "... is not valid JSON 受け取ったもの: "<!DOCTYPE html><html" NG | Unexpected end of JSON input 受け取ったもの: ""

JSON は二重引用符しか許しません'a' は JSON ではありません。

javascript
const res = await fetch(url);

if (!res.ok) {
throw new Error(`${res.status} ${res.statusText}`);
}

const type = res.headers.get('content-type') ?? '';

if (!type.includes('application/json')) {
throw new Error(`JSON ではありません: ${type} / ${(await res.text()).slice(0, 80)}`);
}

const data = await res.json();
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
3 1

JSON に末尾のカンマは書けません。 JavaScript のオブジェクトリテラルとは違います。

text
SyntaxError: Cannot use import statement outside a module
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
8 位置 7 → ":1,}"

空文字も JSON ではありません。応答が空だったときにこれが出ます。

JavaScript では書ける JSON では書けない
{ 'a': 1 } 単引用符
{ a: 1 } 引用符なしのキー
{ "a": 1, } 末尾のカンマ
// コメント コメント
{ a: undefined } undefined

Unexpected token '<'」が出たら

JSON のつもりで HTML を受け取っています。 API が 404 や 500 を返し、 エラーページの HTML が来ているのがほとんどです。

< は「HTML が返ってきた」という合図です。 JSON の書き方を直しても解決しません。

直しかた

中身を見てから解析します。

受け取ったものの先頭を出せば、何が返ってきたのかすぐ分かります。 <!DOCTYPE が見えた時点で、JSON の書き方を疑う必要はありません。

通信の場合は、解析する前に状態コードと Content-Typeを見てください。

この環境では通信できないので、上は実行していません。形だけ示しています。

原因3: 環境が対応していない書き方

新しい構文を古い処理系で読むと、構文として読めません。

ここでは動きますが、?. は ES2020、at() は ES2022 です。 古いブラウザや古い Node では Unexpected token '.' などになります。

「自分の環境では動くのに、相手の環境で構文エラー」はこれです。 node -v と、実際に読み込んでいる環境の版を確かめてください。

原因4: 読み込み方が合っていない

import / exportモジュールとして読み込まれたときだけ書けます。

  • Node … ファイルを .mjs にするか、package.json"type": "module"
  • ブラウザ … <script type="module">

.js のまま import を書いて、CommonJS として読み込まれるのがよくある形です。

処理系によって文言が違う

同じ間違いでも書いてある文が違います。自分の環境の文言で検索してください。

間違い Node / Chrome(V8) Firefox Safari
{ a: 1 b: 2 } Unexpected identifier 'b' expected , after property value Unexpected identifier 'b'
閉じ忘れ Unexpected end of input expected expression, got end of script Unexpected end of script

このページの実行結果は Node 22.22.3 のものです。文言は版によっても変わります。

探しかたの順序

  1. エラーの位置の1つ手前を見る。 そこが壊れている
  2. JSON の文字があるか見る。あれば JSON.parse に渡したものを疑う
  3. '<' があれば HTML が返ってきている。通信を疑う
  4. 括弧・引用符の対応をエディタの色分けで見る
  5. それでも分からなければ、半分に切って試す。どちらで出るかで場所が絞れる

position が出ているときは、その前後を切り出すと原因がすぐ見えます。

JSON そのものの決まり(何が消え、何が例外になるか)はこちらです。 → JSON.parse() と JSON.stringify()

読み込んだ文字列を安全に扱う形(try で囲んで失敗を返す)は、JSON のページに実例があります。 → 文字列を数値に変換する

この記事の根拠

  1. Error Handling and Language Extensions — ECMAScript® 2026 Language Specificationtc39.es
  2. JSON.parse — ECMAScript® 2026 Language Specificationtc39.es
  3. SyntaxError — MDNdeveloper.mozilla.org

掲載しているコード例は、公開前に読み手が押したときに動くのと同じもので実行して出力を突き合わせています。結果はリポジトリに残しています。

このページの原文(Markdown)