Error と try / catch / finally / throw

Error が持っているもの、throw できるもの、finally が必ず動くこと、JSON にすると空になる理由、 cause で原因を繋ぐ書き方、独自のエラーを作って種類で分ける方法までを実行して確かめます。

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

Error が持っているのは、種類・文言・スタックトレースの3つです。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
Error 壊れた Error: 壊れた string
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
TypeError true RangeError true SyntaxError true ReferenceError true

namemessage: で繋いだものが、文字列にしたときの形です。

組み込みの種類

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
object true string false number false
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
理由が分かる | string (message が無い) | undefined

すべて Error を継承しています。 だから instanceof Error で一括して受けられます。

よく出る2つは、それぞれ独立したページで扱っています。 → TypeError: x is not a functionSyntaxError: Unexpected token

種類 いつ出るか
TypeError 型が合わない(関数でないものを呼んだ、null の中身を読んだ)
RangeError 値が範囲の外(配列の長さ、toFixed の桁)
ReferenceError 名前が見つからない
SyntaxError 構文として読めない(JSON.parse を含む)

throw できるものは何でも

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
finally 成功 finally 失敗
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
中身を見ないなら省略できる

文字列も数値も投げられます。ですが投げないでください。

Error でないものを投げると、messagestack も付きません。 受け取った側は何が起きたか調べられません

javascript
const error = new Error('壊れた');

console.log(JSON.stringify(error));
console.log(Object.keys(error));
{} []
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
{"name":"Error","message":"壊れた","stack":"Error: 壊れた"}

finally は必ず動く

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
ユーザーの取得に失敗 通信できない
javascript
try {
JSON.parse('x');
} catch (error) {
throw new Error('設定を読めません');
}

return より後に動きます。 後始末(閉じる・解放する・止める)を書く場所です。

finally の中で return すると、trycatch の結果を上書きします。 書かないでください。

使わない引数は省ける

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
NotFoundError 見つかりません: 7 7 true true
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
404 として扱う こちらの不具合 不明

JSON にすると空になる

これがいちばん事故になります。

javascript
try {
JSON.parse('x');
} catch {
// 何もしない
}
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
{ a: 1 } null

namemessagestack も、列挙されないので消えます。

ログに送ったつもりで {} だけが残る、というのはこれが原因です。 自分で取り出してください。

JSON.parse() と JSON.stringify()

原因を繋ぐ

cause で、元の失敗を保ったまま包み直せます(ES2022)。

握りつぶさずに、文脈だけを足せます。

これだと元の SyntaxError が消えますcause を付けてください。

独自のエラーを作る

種類で分けたいときに作ります。

super(message) を呼び、name を自分で入れます。 → class — 作る・継承する・隠す

受け取る側は種類で分けられます。

文言で分岐しないでください。 文言は処理系や版で変わります。 種類(instanceof)か、自分で付けた印(code など)で分けます。

よくある間違い

何でも catch して握りつぶす

問題が消えたのではなく、見えなくなっただけです。 記録するか、包んで投げ直すか、どちらかにしてください。

想定外まで受けてしまう

受けたい種類だけ受け、それ以外は投げ直す。 そうしないと、想定外の不具合まで null に化けます。

失敗したときにやり直す形は、こちらにまとめています。 → 失敗したら再試行する

try の範囲が広すぎる

try に何十行も入れると、どこで失敗したのか分からなくなります。 落ちうる1行だけを囲んでください。

まとめ

  • Error が持つのは種類・文言・スタックトレース
  • 組み込みの種類はすべて Error を継承している
  • Error 以外を投げない。 messagestack も付かない
  • finallyreturn より後に動く。中で return しない
  • JSON.stringify(error){} 自分で取り出す
  • 包み直すときは cause で元を残す
  • 分岐は文言ではなく種類

この記事の根拠

  1. Error Objects — ECMAScript® 2026 Language Specificationtc39.es
  2. The try Statement — ECMAScript® 2026 Language Specificationtc39.es
  3. Error.prototype.cause — MDNdeveloper.mozilla.org

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

このページの原文(Markdown)