概要
エラーハンドリングとは、「例外を防ぐこと」ではない。
それは「例外が起きたときに、どう受け止め、誰に、どう伝えるか」の設計である。
本稿では以下の視点から、実用的なエラーハンドリングの設計を体系化する:
- try/catchの設置場所と粒度
- 例外のログと通知の分離
- 再スローと再試行の設計
- エラー分類とユーザーへの伝え方
- グローバルエラーバウンダリと復旧戦略
1. try/catchの基本構造と設計思想
try {
const data = await fetchData();
render(data);
} catch (e) {
showError(e.message);
}
- ✅ catchブロックでは必ずログ + UI通知を行う
- ❌ 空のcatchは絶対NG(例外を握り潰す)
2. catchブロックの責務分離
try {
await riskyProcess();
} catch (e) {
logError(e); // ✅ 開発者用ログ
notifyUser(e); // ✅ ユーザー用メッセージ
}
- ✅ 開発者向けログは詳細に
- ✅ ユーザー通知は簡潔に(不安にさせない)
3. エラーの種類と対応の分離
エラー分類 | 例 | ユーザー対応 |
---|---|---|
ユーザー操作系 | 入力ミス、無効な値 | 明確なバリデーションで制御 |
ネットワーク系 | タイムアウト、サーバーダウン | 再試行・リトライ導線 |
アプリ側バグ | 未定義変数、null参照など | ログ + 通知 + 再発防止 |
想定外例外 | 外部ライブラリ、型不一致など | フォールバック設計が必要 |
4. 再スローと例外の巻き取り
function loadData() {
try {
return fetchData();
} catch (e) {
logError(e);
throw e; // ✅ 呼び出し元に“委譲”する
}
}
- ✅ 例外をログしてそのまま再スロー
- ✅ UIで通知したい場合は“最上位”で巻き取る
5. グローバルエラーキャッチと設計境界
✅ 未処理のPromiseを拾う
window.addEventListener('unhandledrejection', (e) => {
logError(e.reason);
});
✅ 実行時エラーのキャッチ
window.addEventListener('error', (e) => {
logError(e.message);
});
→ ✅ あくまで最終防波堤として設置する(ローカルで拾うのが原則)
6. UI通知のパターン化
- ✅ トースト:軽微な失敗(再試行可能)
- ✅ モーダル:致命的な失敗(UIをブロック)
- ✅ インライン:フォームエラーや局所的な問題
notifyUser('保存に失敗しました。もう一度お試しください。');
→ ✅ 文言は“冷静・簡潔・解決策を含む”ことが理想
7. エラーをデザインする:コード例
try {
await saveData(formInput);
showSuccess('保存しました');
} catch (e) {
if (e instanceof ValidationError) {
showFormErrors(e.details);
} else if (e instanceof NetworkError) {
showToast('通信に失敗しました。再試行してください。');
} else {
logError(e);
showError('予期せぬエラーが発生しました');
}
}
→ ✅ 独自エラー型による分類設計が有効(class ValidationError extends Error
など)
設計判断フロー
① この処理は失敗し得る? → try/catch設置
② 失敗時に伝えるべき情報は? → log + notify に分離
③ 呼び出し元に伝えるべき? → throwを再スロー
④ 再試行できる? → retry戦略とUI導線を設計
⑤ 想定外の例外? → グローバルcatchでログと復旧設計
よくあるミスと対策
❌ catchしたエラーを握り潰す
→ ✅ 必ずログかユーザー通知へつなげる
❌ すべてのエラーに同じ通知
→ ✅ エラーの種類ごとにUI反応を設計する
❌ グローバルエラーでしか検知できない
→ ✅ 例外境界を意識し、局所で明示的に処理する
結語
“エラー処理”とは、例外を潰すことではない。
それは、アプリケーションが“壊れないように、正しく壊れる”ための構造設計である。
- 捕まえる場所を設計する
- 伝える内容を整理する
- ログとUIを分けて考える
- 状態を破壊しないよう巻き取る
- 再試行やフォールバックを明示する
優れたエラーハンドリングは、ユーザーと開発者の両方を救う設計資産である。