TL

例外処理(エラーハンドリング)

「処理が続けられない事態」をエラーとして投げ、呼び出し側がまとめて受け止める仕組み。本来の処理とエラー処理を分けて書けるのが利点。

中級エラーハンドリング例外ベストプラクティス最終更新: 2026-06-04
TL;DR要点だけ先に
  • 1.例外処理は 異常事態を“投げて(throw)”、対処できる場所で“捕まえる(catch)”仕組み。正常系とエラー系を分けて書ける。
  • 2.捕まえなければ呼び出し元へ自動で伝播し、最後まで誰も処理しなければプログラムが落ちる。finally は成功・失敗どちらでも必ず実行される。
  • 3.最大のアンチパターンは“握りつぶし”(catch で何もしない)。リソース解放は finally / using で確実に、catch は本当に対処できる所だけに置く。

なぜ「戻り値」で返さないのか

エラーを「特別な戻り値」で表す方法(後述のエラーコード方式)には弱点があります。呼び出すたびに結果を確認しないと、エラーを見落とせてしまうこと、そしてエラー処理のコードが本筋に混ざって読みにくくなることです。

例外方式は、異常が起きた瞬間に処理を中断し、チェックを書き忘れても勝手に下へ進めないようにします。これにより「気づかないままおかしな状態で進む」事故を防げます。

// 例外を投げる側
function divide(a, b) {
  if (b === 0) {
    throw new Error('0 で割れません'); // 異常を“投げる”
  }
  return a / b;
}

// 受け止める側
try {
  const result = divide(10, 0);
  console.log(result);       // ここは実行されない
} catch (err) {
  console.error(err.message); // "0 で割れません"
}

try / catch / finally

例外処理の基本は3つのブロックです。役割を分けて覚えると混乱しません。

ブロックいつ実行されるか役割
tryまず必ず入る失敗するかもしれない本来の処理を書く
catchtry の中で例外が起きたときだけエラーの後始末・代替処理・ログ
finally成功でも失敗でも必ず最後にリソース解放など、どちらにせよ要る後片付け
finally は return より後でも走る

try の中で return しても、finally はその後で必ず実行されます。途中で抜けても確実に動くので、ファイルや接続を閉じる処理の置き場所として最適です。逆に finally の中で return すると try の戻り値を上書きしてしまうので、そこに return は書かないのが無難。

エラーの伝播(どこで捕まえるか)

catch がない関数で例外が起きると、その例外は呼び出し元へ自動的にさかのぼっていきます。これを伝播(propagation)と呼びます。途中の関数が捕まえなければ、さらに上へ。最後まで誰も catch しなければ、プログラム自体が異常終了します。

function load() {
  throw new Error('読み込み失敗');
}
function process() {
  load();          // ここでは catch しない → そのまま上へ伝播
}
function main() {
  try {
    process();     // ここでまとめて受け止める
  } catch (err) {
    console.error('処理を中断:', err.message);
  }
}

ポイントは、**「対処できる場所まで素通りさせてよい」**ということ。途中の関数が中身を知らなくても、適切な場所で1か所だけ捕まえれば済みます。これが「正常系とエラー系を分けられる」という利点の実体です。

“とりあえず全部 catch” は早すぎる

低レイヤーの関数で何でもかんでも捕まえると、上の層は「成功したのか失敗したのか」が分からなくなります。自分が本当に対処(リトライ・代替・ユーザー通知)できる層でだけ捕まえ、それ以外は伝播に任せるのが基本。捕まえたけど対処できないなら、throw で投げ直しましょう。

エラーコード方式 vs 例外方式

エラーの伝え方には大きく2系統あります。言語によって主流が異なり(Go や C はコード方式寄り、Java や Python は例外寄り)、どちらが「正しい」というより向き不向きがあります。

観点エラーコード方式(戻り値で返す)例外方式(throw / catch)
伝え方戻り値やエラー値で表す例外を投げて中断・伝播させる
見落としチェックを書き忘れると素通り捕まえないと勝手には進まない
コードの見た目本筋にエラー確認が混ざる正常系とエラー系を分離できる
伝播毎段で手動で上へ返す必要自動で呼び出し元へさかのぼる
コスト軽い(ただの分岐)投げる瞬間は比較的重い
例外は“例外的なこと”に使う

「ユーザーが空欄で送信した」のような想定内でよく起きることは、例外より戻り値や検証で素直に表すほうが読みやすく、速いことが多いです。例外は「ファイルが壊れていた」「DB に繋がらない」など、本来は起きないはずの事態に取っておくのが目安。throw を通常のフロー制御(ループ脱出など)に使うのはアンチパターンです。

リソース解放を確実に

ファイル・ネットワーク接続・ロックなどは、処理が成功しても失敗しても必ず閉じる必要があります。途中で例外が飛んでも解放されるよう、finally か、それを言語が肩代わりする仕組み(Python の with、C# / Java の using / try-with-resources)を使います。

# with は、ブロックを抜けるとき(例外時も含めて)自動で close する
with open('data.txt') as f:
    data = f.read()
    process(data)        # ここで例外が出ても f は確実に閉じられる
# ここに来た時点で f はもう閉じている

手で書くなら finally です。try の前ではなく中で開き、finally で閉じるのが定石です。

const conn = openConnection();
try {
  conn.query('...');
} finally {
  conn.close(); // 成功でも例外でも必ず閉じる
}

握りつぶし禁止(最大のアンチパターン)

空の catch でエラーを消さない

最もやってはいけないのが、**捕まえたエラーを握りつぶす(swallow する)**こと。下のように catch で何もしないと、バグが起きても無言で進み続け、後で全く別の場所で原因不明の不具合として現れます。デバッグが地獄になる典型例です。

// アンチパターン:握りつぶし
try {
  riskyCall();
} catch (e) {
  // 何もしない ← エラーがなかったことにされる
}

捕まえたら最低限、ログに残すか、対処できないなら投げ直す(再スロー)。「ここでは握って正常に続けてよい」と判断したなら、その理由をコメントで残しましょう。

その他、現場でよく刺さるポイント:

  • 広すぎる catch を避けるcatch (Exception) のように何でも捕まえると、想定外のバグまで隠してしまう。捕まえる型はできるだけ具体的に。
  • 元の原因を捨てない:投げ直すときは元の例外を「原因(cause)」として連鎖させ、スタックトレースを残す。新しいエラーで上書きして握りつぶさない。
  • エラーメッセージは具体的に:「失敗しました」ではなく「ファイル X が見つかりません」など、後から原因を特定できる情報を載せる。
catch の中で例外を出さない

catchfinally の中で新たに例外を投げると、元のエラーが上書きされて消えることがあります(特に finally 内)。後始末のコードこそ、できるだけ安全に・追加の例外を出さないように書くのが鉄則です。

まとめと関連

  • 例外処理は「異常を投げ、対処できる場所で捕まえ、後始末は確実に」という分業の仕組み。
  • 捕まえるのは対処できる層だけ、解放は finally / with / using で確実に、握りつぶしは厳禁
  • 「想定内のこと」は例外ではなく戻り値で表すなど、コストと読みやすさのバランスで使い分ける。

例外を投げたり受けたりするのは関数の境界です。どんなエラーを投げ得るかを型で表現する言語もあり、これは型システムの話題(検査例外やResult型)につながります。また非同期処理では、例外の捕まえ方が同期コードと変わる(Promise.catchasync/await + try/catch)点にも注意が必要です。

プログラミング Article

例外処理(エラーハンドリング)を実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

エラーハンドリング

比較で見る軸

難易度: intermediate / カテゴリ: プログラミング / タグ数: 3

導入後に効く点

捕まえなければ呼び出し元へ自動で伝播し、最後まで誰も処理しなければプログラムが落ちる。finally は成功・失敗どちらでも必ず実行される。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
intermediate
カテゴリ
プログラミング
タグ数
3

判断チェックリスト

  • 自社の用途が「エラーハンドリング / 例外」に近いか確認する。
  • 強みである「例外処理は 異常事態を“投げて(throw)”、対処できる場所で“捕まえる(catch)”仕組み。正常系とエラー系を分けて書ける。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

エラーハンドリング例外ベストプラクティスエラーハンドリング例外ベストプラクティス
参考: 公式情報