window.onerror でグローバルエラーを捕捉 - JavaScript

try-catch で囲んでいない部分でエラーが発生すると、通常はスクリプトの実行が止まってしまいます。window.onerror を使えば、そうしたグローバルなエラーを最後の砦として捕捉できます。

基本的な使い方

window.onerror にハンドラを設定すると、未捕捉のエラーを受け取れます。

window.onerror = function(message, source, lineno, colno, error) {
  console.log('エラーメッセージ:', message);
  console.log('ファイル:', source);
  console.log('行番号:', lineno);
  console.log('列番号:', colno);
  console.log('Errorオブジェクト:', error);
  
  return true; // デフォルトのエラー出力を抑制
};

コールバックの引数

messageエラーメッセージの文字列
sourceエラーが発生したスクリプトの URL
linenoエラーが発生した行番号
colnoエラーが発生した列番号
errorError オブジェクト(スタックトレース含む)

error 引数が追加されたのは比較的最近のブラウザからなので、古いブラウザでは undefined になることがあります。

addEventListener との違い

onerror プロパティに直接代入する方法と、addEventListener を使う方法があります。

// プロパティに代入(上書きされる可能性あり)
window.onerror = function(message) {
  console.log(message);
};

// addEventListener(複数登録可能)
window.addEventListener('error', function(event) {
  console.log(event.message);
});

addEventListener を使うと、複数のハンドラを登録できます。ただし、引数の形式が異なる点に注意が必要です。

実践的なエラーログ収集

本番環境では、エラー情報をサーバーに送信することが一般的です。

window.onerror = function(message, source, lineno, colno, error) {
  const errorData = {
    message: message,
    source: source,
    lineno: lineno,
    colno: colno,
    stack: error?.stack,
    userAgent: navigator.userAgent,
    url: location.href,
    timestamp: new Date().toISOString()
  };
  
  // ビーコンで送信(ページ離脱時も確実に送れる)
  navigator.sendBeacon('/api/errors', JSON.stringify(errorData));
  
  return false; // コンソールにも出力する
};

戻り値の意味

ハンドラが true を返すと、デフォルトのエラー出力(コンソールへの表示)が抑制されます。

return true

コンソールにエラーを表示しない

return false / 何も返さない

コンソールにもエラーを表示する

開発中は false を返してコンソールにも出力し、本番では状況に応じて決めます。

クロスオリジンのスクリプトエラー

外部ドメインから読み込んだスクリプトのエラーは、セキュリティ上の理由で詳細が隠されます。

// 外部スクリプトのエラー
window.onerror = function(message, source, lineno, colno, error) {
  console.log(message); // "Script error."
  console.log(lineno);  // 0
  console.log(error);   // null
};

詳細を取得するには、スクリプトの読み込み時に crossorigin 属性を付け、サーバー側で CORS ヘッダーを返す必要があります。

<script src="https://example.com/script.js" crossorigin="anonymous"></script>

window.onerror の限界

以下のエラーは window.onerror では捕捉できません。

Promise のリジェクション

unhandledrejection イベントを使います。

リソースの読み込みエラー

画像やスクリプトの 404 エラーなどは error イベントを個別に監視します。

構文エラー

スクリプトのパース時に発生する SyntaxError は onerror に到達しません。

リソースエラーの監視

画像や CSS などの読み込み失敗を検知するには、キャプチャフェーズでイベントを監視します。

window.addEventListener('error', function(event) {
  if (event.target !== window) {
    console.log('リソース読み込みエラー:', event.target.src || event.target.href);
  }
}, true); // キャプチャフェーズで監視

グローバルエラー処理の組み合わせ

堅牢なエラー監視には、複数の仕組みを組み合わせます。

// 同期エラー
window.onerror = handleGlobalError;

// Promise のエラー
window.addEventListener('unhandledrejection', handlePromiseError);

// リソースエラー
window.addEventListener('error', handleResourceError, true);

これらを組み合わせることで、アプリケーション全体のエラーを漏れなく捕捉できます。