# 画面設計書 6-グローバルエラーページ (Global Error)

## 概要

App Routerにおいてアプリケーション全体でキャッチされなかったエラーを表示する最上位エラーバウンダリの設計書。サーバーエラーとクライアントエラーを判別して異なるメッセージを表示する。

### 本画面の処理概要

**業務上の目的・背景**：App Routerを使用するNext.jsアプリケーションでは、ルートレイアウトを含むアプリケーション全体で発生したエラーをキャッチするための最上位エラーバウンダリが必要である。本コンポーネントは、Server ComponentやClient Componentで発生した未キャッチのエラーを捕捉し、ユーザーにエラー情報と回復手段（ページリロード、前のページに戻る）を提供する。サーバーエラー（digestあり）とクライアントエラー（digestなし）を区別し、それぞれ異なるメッセージとアクション（ボタン）を表示する。また、ISR（Incremental Static Regeneration）のエラーハンドリングもサポートする。

**画面へのアクセス方法**：アプリケーション全体でキャッチされないエラーが発生した場合に自動的に表示される。ユーザーが`app/global-error.tsx`を作成している場合はそちらが優先される。

**主要な操作・処理内容**：
1. errorオブジェクトのdigestプロパティの有無でサーバーエラー/クライアントエラーを判別する
2. サーバーエラーの場合は「This page failed to load」タイトルと「Something went wrong while loading this page.」メッセージを表示する
3. クライアントエラーの場合は「This page crashed」タイトルと「An error occurred while running this page.」メッセージを表示する
4. 「Reload page」ボタンを表示し、クリック時にページをリロードする（form submit）
5. クライアントエラーの場合のみ「Go back」ボタンを追加表示し、クリック時にブラウザの履歴を1つ戻る（履歴がない場合はトップページに遷移）
6. サーバーエラーの場合のみ「If this keeps happening, it may be a server issue.」ヒントメッセージを表示する
7. digestが存在する場合、エラーリファレンスコードを画面下部に表示する
8. `HandleISRError`コンポーネントを使用してISRの静的生成時にエラーを再スローする
9. ダークモード対応のCSSテーマ変数を使用する

**画面遷移**：
- 遷移元：App Routerのエラーバウンダリでキャッチされなかったエラー発生時
- 遷移先：「Reload page」ボタンでページリロード、「Go back」ボタンでブラウザ履歴を1つ戻る（または「/」に遷移）

**権限による表示制御**：権限による表示制御は行わない。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 16 | エラーハンドリング | 主機能 | アプリケーション全体のキャッチされなかったエラーの表示処理（サーバーエラー・クライアントエラーの判別表示） |
| 13 | App Router | 補助機能 | App RouterのError Boundary機構との統合 |
| 36 | Incremental Static Regeneration（ISR） | API連携 | HandleISRErrorコンポーネントによるISRエラー時の再検証処理 |

## 画面種別

エラー表示（グローバルエラーバウンダリ）

## URL/ルーティング

特定のURLパターンは持たない。エラー発生時のURLのまま表示される。

## 入出力項目

| 項目名 | 入出力 | 型 | 必須 | 説明 |
|--------|--------|------|------|------|
| error | 入力 | any | はい | キャッチされたエラーオブジェクト。digestプロパティの有無でサーバー/クライアントエラーを判別 |

## 表示項目

| 項目名 | 表示位置 | 説明 |
|--------|----------|------|
| エラーアイコン | カード上部 | SVGによるエラーアイコン（丸枠＋警告マーク、赤色） |
| タイトル | h1要素 | サーバーエラー: "This page failed to load" / クライアントエラー: "This page crashed" |
| メッセージ | p要素 | サーバーエラー: "Something went wrong while loading this page." / クライアントエラー: "An error occurred while running this page." |
| ヒント | p要素 | サーバーエラー: "If this keeps happening, it may be a server issue." / クライアントエラー: "Reloading usually fixes this." |
| Reload pageボタン | ボタン領域 | form submitによるページリロード（常時表示） |
| Go backボタン | ボタン領域 | クライアントエラー時のみ表示。ブラウザ履歴を1つ戻る |
| エラーリファレンス | カード下部 | digestが存在する場合のみ「Error reference: {digest}」を表示 |

## イベント仕様

### 1-Reload pageボタン押下

`<form>`タグの`submit`イベントによりページがリロードされる。JavaScriptによるハンドラではなく、フォームのデフォルトsubmit動作を利用しているため、JavaScriptが無効な環境でも動作する。

### 2-Go backボタン押下（クライアントエラー時のみ）

`onClick`ハンドラで以下の処理を実行する：
- `window.history.length > 1` の場合：`window.history.back()` でブラウザ履歴を1つ戻る
- それ以外の場合：`window.location.href = '/'` でトップページに遷移する

## データベース更新仕様

### 操作別データベース影響一覧

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| なし | - | - | 本画面はデータベースへのアクセスを行わない |

### テーブル別更新項目詳細

データベース操作なし。

## メッセージ仕様

| メッセージID | 種別 | 条件 | メッセージ内容 |
|-------------|------|------|----------------|
| TITLE-SERVER | エラー | digest存在（サーバーエラー） | This page failed to load |
| TITLE-CLIENT | エラー | digestなし（クライアントエラー） | This page crashed |
| MSG-SERVER | エラー | digest存在 | Something went wrong while loading this page. |
| MSG-CLIENT | エラー | digestなし | An error occurred while running this page. |
| HINT-SERVER | 情報 | digest存在 | If this keeps happening, it may be a server issue. |
| HINT-CLIENT | 情報 | digestなし | Reloading usually fixes this. |

## 例外処理

| 例外条件 | 挙動 |
|----------|------|
| ISRの静的生成中にエラーが発生した場合 | HandleISRErrorコンポーネントがエラーを再スローし、前回のキャッシュを維持する |

## 備考

- `'use client'`ディレクティブが設定されたClient Componentである
- ダークモード対応はCSS変数（`--next-error-*`）とprefers-color-schemeメディアクエリで実装
- html要素に`id="__next_error__"`が設定される
- `GlobalErrorComponent`型がエクスポートされ、ユーザーカスタムグローバルエラーの型定義に使用可能
- エラーアイコンは40x40のSVGで、赤色（#dc2626）のビックリマーク付き丸枠
- `errorStyles`と`errorThemeCss`は`error-styles.tsx`から共有され、No.7（App Error）と共通のスタイル定義を使用

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | global-error.tsx | `packages/next/src/client/components/builtin/global-error.tsx` | L6-8: `GlobalErrorComponent`型 - error propを受け取る |
| 1-2 | error-styles.tsx | `packages/next/src/client/components/builtin/error-styles.tsx` | L3-86: `errorStyles`オブジェクト - 各要素のスタイル定義 |
| 1-3 | error-styles.tsx | `packages/next/src/client/components/builtin/error-styles.tsx` | L88-124: `errorThemeCss` - ダークモード対応CSS変数 |

**読解のコツ**: `error.digest`の存在がサーバーエラー/クライアントエラーの判別キーである。digestはNext.jsがサーバーサイドのエラーに付与する一意識別子。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | global-error.tsx | `packages/next/src/client/components/builtin/global-error.tsx` | L10-77: `DefaultGlobalError`関数コンポーネント |

**主要処理フロー**:
1. **L11**: `error?.digest`からdigest値を取得
2. **L12**: `!!digest`でサーバーエラーかを判定
3. **L16-19**: サーバー/クライアントに応じたtitle, message, hintを設定
4. **L25-27**: html/head構造とerrorThemeCssの適用
5. **L30**: `HandleISRError`コンポーネントの配置
6. **L31-73**: エラーカード（アイコン、タイトル、メッセージ、ボタン群、digest表示）のレンダリング
7. **L44-47**: Reload pageボタン（form submit）
8. **L48-61**: Go backボタン（クライアントエラー時のみ、history.back()またはトップ遷移）

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | handle-isr-error.tsx | `packages/next/src/client/components/handle-isr-error.tsx` | L1-23: HandleISRError - ISR時のエラー再スロー |

**主要処理フロー**:
- **L1-6**: サーバーサイドでのみworkAsyncStorageを取得
- **L12-19**: ISR静的生成中であればエラーを再スローしてキャッシュを維持

#### Step 4: スタイルとアイコンを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | error-styles.tsx | `packages/next/src/client/components/builtin/error-styles.tsx` | L126-152: `ErrorIcon`コンポーネント - SVGアイコン |

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

```
App Router Error Boundary (未キャッチエラー)
    |
    +-- DefaultGlobalError({ error })
            |
            +-- <html id="__next_error__">
            +-- <head>
            |       +-- errorThemeCss (CSS変数定義)
            |
            +-- <body>
                    |
                    +-- HandleISRError({ error })
                    |       +-- workAsyncStorage.getStore()
                    |       +-- ISR時: throw error
                    |
                    +-- エラーカード
                            +-- ErrorIcon (SVG)
                            +-- <h1> title
                            +-- <p> message
                            +-- <p> hint
                            +-- <form> Reload page button
                            +-- <button> Go back (client error only)
                            +-- digest表示 (server error only)
```

### データフロー図

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

error object --------> DefaultGlobalError() --------> HTML (完全なページ)
  |                     |
  +-- error.digest ---> isServerError判定
  |                     |
  |                     +-- true: サーバーエラーUI
  |                     |    - "This page failed to load"
  |                     |    - Reload page ボタン
  |                     |    - Error reference表示
  |                     |
  |                     +-- false: クライアントエラーUI
  |                          - "This page crashed"
  |                          - Reload page + Go back ボタン
  |
  +-- error (ISR) ---> HandleISRError
                        +-- 静的生成中: エラー再スロー
                        +-- それ以外: null (表示なし)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| global-error.tsx | `packages/next/src/client/components/builtin/global-error.tsx` | ソース | グローバルエラーページのメインコンポーネント |
| error-styles.tsx | `packages/next/src/client/components/builtin/error-styles.tsx` | ソース | エラーページ共通スタイル定義とErrorIconコンポーネント |
| handle-isr-error.tsx | `packages/next/src/client/components/handle-isr-error.tsx` | ソース | ISRエラーハンドリングコンポーネント |
| work-async-storage.external.ts | `packages/next/src/server/app-render/work-async-storage.external.ts` | ソース | ワーク非同期ストレージ（ISR判定用） |
