# 通知設計書 34-ランタイムエラーオーバーレイ

## 概要

本ドキュメントは、Next.js開発サーバーにおけるランタイムエラーオーバーレイの設計について記載する。ランタイムエラー発生時にブラウザ上にエラー詳細（スタックトレース、コードフレーム含む）をオーバーレイ表示する通知機能である。

### 本通知の処理概要

ランタイムエラーオーバーレイは、アプリケーションの実行時にJavaScriptエラーが発生した場合、ブラウザ画面上にオーバーレイダイアログとしてエラーの詳細情報を表示する機能である。

**業務上の目的・背景**：開発中にランタイムエラーが発生した場合、エラーの原因を迅速に特定し修正できるようにすることが目的である。スタックトレースやコードフレームを視覚的に表示することで、エラー箇所の特定を容易にする。複数のエラーが発生している場合はナビゲーションで切り替えが可能であり、効率的なデバッグを支援する。

**通知の送信タイミング**：クライアントサイドまたはサーバーサイドでランタイムエラーが発生し、`runtimeErrors`配列にエラーが追加された場合に表示される。エラーはReactのエラーバウンダリやグローバルエラーハンドラで捕捉される。

**通知の受信者**：開発中のアプリケーションをブラウザで表示している開発者。

**通知内容の概要**：エラーの種別ラベル（Runtime Error / Recoverable Error / Console Error等）、エラーメッセージ、環境名（Server / Client等）、エラーコード、スタックトレース（ファイルパス、行番号、カラム番号）、コードフレーム（エラー箇所周辺のソースコード）が表示される。また、複数エラーがある場合はナビゲーション（前へ/次へ）が提供される。

**期待されるアクション**：開発者はオーバーレイに表示されたスタックトレースとコードフレームからエラーの原因箇所を特定し、ソースコードを修正する。サーバーサイドエラーの場合はオーバーレイを閉じることはできないが、クライアントサイドエラーの場合は閉じて動作確認を継続できる。

## 通知種別

ブラウザUI / Dev Overlay（オーバーレイダイアログ）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（ランタイムエラー捕捉後、Reactコンポーネントで描画） |
| 優先度 | 高（ただしビルドエラーが優先される） |
| リトライ | 無し |

### 送信先決定ロジック

クライアントサイドでエラーが発生した場合はブラウザ内で直接処理される。サーバーサイドでエラーが発生した場合はWebSocket経由でブラウザに送信される。`ErrorOverlay`コンポーネントが`runtimeErrors`配列を監視し、エラーが存在し`buildError`がnullの場合に`Errors`コンポーネントを描画する。

## 通知テンプレート

### ブラウザUI表示の場合

| 項目 | 内容 |
|-----|------|
| ヘッダーラベル | Runtime {ErrorName} / Recoverable {ErrorName} / Console {ErrorName} |
| エラーメッセージ | エラーのmessageプロパティ（環境名プレフィックス除去済み） |
| 環境名ラベル | Server / edge-server / Client（該当する場合） |
| コードフレーム | 最初のファーストパーティフレームのソースコード |
| コールスタック | フレーム一覧（ignored以外） |
| 形式 | HTMLオーバーレイ |

### 本文テンプレート

```
[Runtime Error]                           [1 of N] [< >]
{errorMessage}

--- Code Frame ---
{filePath}:{lineNumber}:{columnNumber}
{sourceCodeWithHighlight}

--- Call Stack ---
  at {methodName} ({file}:{line}:{column})
  at {methodName} ({file}:{line}:{column})
  ...
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| error | エラーオブジェクト | ReadyRuntimeError.error | Yes |
| error.message | エラーメッセージ | Error.message | Yes |
| error.environmentName | 実行環境名 | Error拡張プロパティ | No |
| errorType | エラー種別ラベル | getErrorTypeLabel() | Yes |
| errorCode | エラーコード | useActiveRuntimeError() | No |
| frames | スタックフレーム配列 | useFrames(activeError) | Yes |
| firstFrame | 最初のファーストパーティフレーム | frames.find(!ignored) | No |
| runtimeErrors | ランタイムエラーの配列 | OverlayState由来 | Yes |
| activeIdx | 現在表示中のエラーインデックス | useActiveRuntimeError() | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ランタイムエラー | JavaScript実行時エラー | runtimeErrors.length > 0 && buildError === null | ランタイムエラーが存在し、ビルドエラーがない場合 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| state.buildError !== null | ビルドエラーがある場合はビルドエラーオーバーレイが優先される |
| runtimeErrors.length === 0 | ランタイムエラーがない場合は表示されない |
| mounted === false | useDelayedRenderでマウント前の場合は表示されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ランタイムエラー発生] --> B[runtimeErrors配列に追加]
    B --> C[ErrorOverlayコンポーネント描画判定]
    C --> D{buildError存在?}
    D -->|Yes| E[BuildError表示（優先）]
    D -->|No| F{runtimeErrors > 0?}
    F -->|No| G[Suspense返却]
    F -->|Yes| H{mounted?}
    H -->|No| G
    H -->|Yes| I[Errorsコンポーネント描画]
    I --> J[useActiveRuntimeError]
    J --> K[useFrames / useErrorDetails]
    K --> L[ErrorOverlayLayout構築]
    L --> M[CodeFrame + CallStack表示]
    M --> N[ブラウザにオーバーレイ表示]
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（データベースは使用しない）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| フレーム解析失敗 | ソースマップが利用できない場合 | フレームが空の場合はコードフレーム表示をスキップ |
| activeErrorがnull | エラー配列が空になった場合 | nullを返してオーバーレイを非表示にする |
| ローディング中 | フレーム解析が進行中 | OverlayBackdropのみを表示するローディング状態 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（開発サーバー稼働中は常時表示可能）

## セキュリティ考慮事項

- エラーメッセージにはファイルパスやソースコードの断片が含まれるが、開発環境のみで使用されるため問題はない
- Dev Overlayは本番ビルドには含まれない
- サーバーサイドエラーの場合、`getErrorSource(error)`で`server`または`edge-server`を判定し、閉じるボタンを無効化する

## 備考

- エラー種別ラベルは`getErrorTypeLabel()`で決定され、`blocking-route`の場合は「Blocking Route」、`dynamic-metadata`の場合は「Ambiguous Metadata」、`recoverable`の場合は「Recoverable {ErrorName}」、`console`の場合は「Console {ErrorName}」、その他は「Runtime {ErrorName}」となる
- 複数エラーがある場合、`ErrorOverlayNav`でエラー間のナビゲーション（前へ/次へ）が可能
- `generateErrorInfo()`でMarkdown形式のエラー情報が生成され、AIアシスタントへの問い合わせに使用可能
- `useFocusTrap`でキーボードフォーカスがオーバーレイ内に閉じ込められる

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、ランタイムエラーの型定義と状態管理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | error-overlay.tsx | `packages/next/src/next-devtools/dev-overlay/components/errors/error-overlay/error-overlay.tsx` | `ErrorBaseProps`（16-22行目）と`ErrorOverlay`のprops。`OverlayState`と`ReadyRuntimeError`の関係を理解する |
| 1-2 | errors.tsx | `packages/next/src/next-devtools/dev-overlay/container/errors.tsx` | `ErrorsProps`（25-30行目）、`ErrorDetails`型（455-481行目）。エラー詳細の4種類（empty/hydration/blocking-route/dynamic-metadata）を理解する |

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | error-overlay.tsx | `packages/next/src/next-devtools/dev-overlay/components/errors/error-overlay/error-overlay.tsx` | `ErrorOverlay`（24-87行目）。64行目の`!runtimeErrors.length`チェック、76行目の`Errors`コンポーネント描画 |

**主要処理フロー**:
1. **52行目**: `state.buildError !== null`ならBuildError（ビルドエラー優先）
2. **64行目**: `!runtimeErrors.length`なら表示なし
3. **70行目**: `!mounted`なら表示なし
4. **76-86行目**: `Errors`コンポーネントを描画

#### Step 3: Errorsコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | errors.tsx | `packages/next/src/next-devtools/dev-overlay/container/errors.tsx` | `Errors`コンポーネント（584-788行目）。`useActiveRuntimeError`、`useFrames`、`useErrorDetails`の3つのフックが中心 |

**主要処理フロー**:
- **593-601行目**: `useActiveRuntimeError`でアクティブなエラーを選択
- **604行目**: `useFrames(activeError)`でスタックフレームを取得
- **606-615行目**: 最初のファーストパーティフレームを特定
- **694行目**: `getErrorSource(error)`でサーバー/クライアント判定
- **701-760行目**: errorDetailsに応じたエラーメッセージの切り替え（hydration/blocking-route/dynamic-metadata/empty）
- **762-788行目**: `ErrorOverlayLayout`で全体レイアウト構築

#### Step 4: RuntimeErrorコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | index.tsx | `packages/next/src/next-devtools/dev-overlay/container/runtime-error/index.tsx` | `RuntimeError`コンポーネント（15-46行目）。CodeFrameとErrorOverlayCallStackの表示 |

### プログラム呼び出し階層図

```
ErrorOverlay [error-overlay.tsx:24]
    |
    +-- useDelayedRender()
    |
    +-- Errors [errors.tsx:584]
           |
           +-- useActiveRuntimeError()
           +-- useFrames()
           +-- useErrorDetails()
           +-- getErrorTypeLabel() [errors.tsx:435]
           +-- getErrorSource()
           |
           +-- ErrorOverlayLayout [error-overlay-layout.tsx:58]
           |      +-- ErrorOverlayNav
           |      +-- ErrorTypeLabel
           |      +-- EnvironmentNameLabel
           |      +-- ErrorMessage
           |      +-- ErrorOverlayToolbar
           |
           +-- RuntimeError [runtime-error/index.tsx:15]
                  +-- useFrames()
                  +-- CodeFrame
                  +-- ErrorOverlayCallStack
```

### データフロー図

```
[入力]                       [処理]                              [出力]

ランタイムエラー           ErrorOverlay判定              ブラウザ
(Error object)   ------>  useActiveRuntimeError   ------>  オーバーレイ
                          useErrorDetails                   ダイアログ
WebSocket                 useFrames                         (エラー種別 +
(server error)   ------>  ErrorOverlayLayout        ------>  メッセージ +
                          RuntimeError                       コードフレーム +
                                                             コールスタック)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| errors.tsx | `packages/next/src/next-devtools/dev-overlay/container/errors.tsx` | ソース | Errorsコンポーネント。エラー詳細の判定と表示、エラー種別ラベル決定 |
| error-overlay.tsx | `packages/next/src/next-devtools/dev-overlay/components/errors/error-overlay/error-overlay.tsx` | ソース | ErrorOverlayコンポーネント。ビルドエラーとランタイムエラーの振り分け |
| index.tsx | `packages/next/src/next-devtools/dev-overlay/container/runtime-error/index.tsx` | ソース | RuntimeErrorコンポーネント。CodeFrameとCallStackの表示 |
| error-overlay-layout.tsx | `packages/next/src/next-devtools/dev-overlay/components/errors/error-overlay-layout/error-overlay-layout.tsx` | ソース | オーバーレイダイアログの全体レイアウト |
