# 画面設計書 43-致命的エラー画面

## 概要

本ドキュメントは、Actual Budgetアプリケーションの「致命的エラー画面」の画面設計書です。アプリケーション実行中に発生した回復不能なエラーをユーザーに通知し、適切な対応手段を提供する画面です。

### 本画面の処理概要

致命的エラー画面は、アプリケーションの初期化失敗、レンダリングエラー、遅延読み込みの失敗など、通常の操作では回復できない重大なエラーが発生した際に表示されるモーダルダイアログです。エラーの種類に応じた適切なメッセージを表示し、ユーザーにアプリケーションの再起動を促します。

**業務上の目的・背景**：アプリケーションに致命的なエラーが発生した場合、ユーザーは白い画面や応答しない状態に直面する可能性があります。この画面は、そのような状況でもユーザーに何が起きているかを明確に伝え、アプリケーションの再起動という解決策を提供することで、ユーザー体験の悪化を最小限に抑えます。また、エラースタックトレースを表示する機能により、開発者やサポートチームへの問題報告を容易にします。

**画面へのアクセス方法**：この画面はユーザーが意図的にアクセスする画面ではありません。アプリケーション内でキャッチされない例外が発生した場合、Reactの`ErrorBoundary`によって自動的に表示されます。URL経由でのアクセスは不可能です。

**主要な操作・処理内容**：
1. エラーメッセージの表示：エラーの種類に応じた適切なメッセージを表示します
2. アプリケーションの再起動：「Restart app」ボタンでアプリケーションを再起動できます
3. エラー詳細の表示：「Show Error」リンクでスタックトレースを表示できます
4. サポートへの誘導：サポートページへのリンクを提供します
5. SharedArrayBuffer回避オプション：特定条件下で非推奨モードでの実行を許可します

**画面遷移**：
- 遷移元：アプリケーション全体（ErrorBoundaryによるキャッチ）
- 遷移先：アプリケーション再起動（window.Actual.relaunch()）

**権限による表示制御**：
- 権限による制御はありません
- 全てのユーザーに対して同じ内容が表示されます

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 53 | 同期サーバー | 遷移先機能 | 致命的エラー発生時の表示・復旧オプション提供 |

## 画面種別

エラー / モーダル

## URL/ルーティング

- **パス**: なし（モーダルとして表示）
- **表示トリガー**: `ErrorBoundary`のFallbackComponent
- **モーダル名**: `fatal-error`（または現在のモーダル名）

## 入出力項目

### 入力項目

| 項目名 | 項目ID | 型 | 必須 | 説明 |
|--------|--------|-----|------|------|
| エラーオブジェクト | error | Error / AppError | 必須 | キャッチされたエラー情報 |

### エラータイプ別プロパティ（AppError）

| プロパティ | 型 | 説明 |
|-----------|-----|------|
| type | string | エラータイプ（'app-init-failure'等） |
| IDBFailure | boolean | IndexedDB失敗フラグ |
| SharedArrayBufferMissing | boolean | SharedArrayBuffer不足フラグ |
| BackendInitFailure | boolean | バックエンド初期化失敗フラグ |

## 表示項目

### ヘッダー

| 項目 | 説明 |
|------|------|
| タイトル | 「Fatal Error」または「Loading Error」（遅延読み込みエラー時） |

### 本文（エラータイプ別）

#### IndexedDB失敗時

| 項目 | 内容 |
|------|------|
| メッセージ | Your browser doesn't support IndexedDB in this environment... |
| 推奨対応 | プライベートブラウジング解除、別ブラウザ使用 |
| サポートリンク | https://actualbudget.org/contact |

#### SharedArrayBuffer不足時

| 項目 | 内容 |
|------|------|
| メッセージ | Actual requires access to SharedArrayBuffer... |
| ドキュメントリンク | https://actualbudget.org/docs/troubleshooting/shared-array-buffer |
| 高度なオプション | 非推奨モードでの実行チェックボックス |
| サポートリンク | https://actualbudget.org/contact |

#### 遅延読み込みエラー時

| 項目 | 内容 |
|------|------|
| メッセージ | There was a problem loading one of the chunks of the application... |
| 推奨対応 | ページリロード、ネットワーク接続確認 |

#### UIエラー時（デフォルト）

| 項目 | 内容 |
|------|------|
| メッセージ | There was an unrecoverable error in the UI. Sorry! |
| サポートリンク | https://actualbudget.org/contact |

### フッター

| 項目 | 説明 |
|------|------|
| Restart appボタン | アプリケーション再起動 |
| Show Errorリンク | スタックトレース表示トグル |
| エラースタック表示エリア | 100pxの高さでスクロール可能 |

## イベント仕様

### 1-Restart appボタン押下

アプリケーションを再起動します。

- **処理**: `window.Actual.relaunch()` 呼び出し（FatalError.tsx 228行目）
- **動作**: Electronアプリの場合はアプリ再起動、Webの場合はページリロード

### 2-Show Errorリンク押下

エラーのスタックトレース表示を切り替えます。

- **処理**: `setShowError` 状態トグル（FatalError.tsx 233行目）
- **表示内容**: `error.stack`（FatalError.tsx 244行目）
- **表示エリア**: 高さ100px、オーバーフロー時スクロール

### 3-サポートリンククリック

外部のサポートページを新しいタブで開きます。

- **URL**: https://actualbudget.org/contact
- **コンポーネント**: `Link` with `variant="external"`

### 4-SharedArrayBuffer回避オプション（高度なオプション）

SharedArrayBuffer不足時のみ表示される回避オプションです。

- **処理手順**:
  1. 「Advanced options」リンクをクリックして展開
  2. リスク了承チェックボックスをON
  3. 「Open Actual」ボタンをクリック
- **処理**: `window.localStorage.setItem('SharedArrayBufferOverride', 'true')` 後にリロード（FatalError.tsx 179-182行目）
- **警告**: データ損失や予算ファイル統合の問題が発生する可能性

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| - | - | - | この画面ではデータベース操作を行いません |

## メッセージ仕様

| エラータイプ | タイトル | メッセージ概要 |
|-------------|---------|---------------|
| IDBFailure | Fatal Error | IndexedDBがサポートされていない（プライベートブラウジング等） |
| SharedArrayBufferMissing | Fatal Error | SharedArrayBufferが利用不可（HTTPS/CORS設定問題） |
| LazyLoadFailedError | Loading Error | アプリケーションチャンクの読み込み失敗 |
| その他 | Fatal Error | 回復不能なUIエラー |

## 例外処理

| 例外状況 | 対応処理 |
|---------|---------|
| IndexedDB初期化失敗 | IDBFailureメッセージ表示、ブラウザ/プライベートモードの確認を促す |
| SharedArrayBuffer不足 | SharedArrayBufferMissingメッセージ表示、トラブルシューティングドキュメントへ誘導 |
| 遅延読み込み失敗 | LazyLoadFailedErrorメッセージ表示、リロード・ネットワーク確認を促す |
| 一般的なUIエラー | 汎用エラーメッセージ表示、サポートへの連絡を促す |

## 備考

- この画面はReactの`ErrorBoundary`によってラップされたコンポーネントで発生したエラーをキャッチします
- `App.tsx`では2箇所で`ErrorBoundary`が使用されています:
  1. メインアプリケーション（AppInner）用（237行目）
  2. モーダル（Modals）用（245行目）
- `LazyLoadFailedError`は`loot-core/src/shared/errors.ts`で定義されたカスタムエラークラスです
- モーダルは`isDismissable={false}`で設定されており、ユーザーが閉じることはできません
- SharedArrayBuffer回避オプションは非推奨であり、データ損失のリスクがあることをユーザーに明示しています
- エラー発生時も`AppBackground`コンポーネントにより背景は適切に表示されます

---

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

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

### 推奨読解順序

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

まず、エラー型の定義とカスタムエラークラスを理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | FatalError.tsx | `packages/desktop-client/src/components/FatalError.tsx` | AppError型の定義（19-24行目）。type、IDBFailure、SharedArrayBufferMissing、BackendInitFailureプロパティ |
| 1-2 | errors.ts | `packages/loot-core/src/shared/errors.ts` | LazyLoadFailedErrorクラスの定義（127-136行目） |

**読解のコツ**: `AppError`は`Error`を拡張した型で、オプショナルなプロパティによりエラーの種類を判別します。

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

処理の起点となるErrorBoundaryの設定を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | App.tsx | `packages/desktop-client/src/components/App.tsx` | ErrorBoundaryの設定（237行目、245行目）、ErrorFallbackコンポーネント（164-171行目） |

**主要処理フロー**:
1. **237行目**: メインアプリケーション用ErrorBoundary
2. **245行目**: モーダル用ErrorBoundary
3. **164-171行目**: ErrorFallbackコンポーネント - AppBackgroundとFatalErrorを表示

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FatalError.tsx | `packages/desktop-client/src/components/FatalError.tsx` | メインコンポーネント全体 |

**主要処理フロー**:
- **198-251行目**: FatalErrorコンポーネント
- **200-202行目**: useModalStateでモーダル状態を取得
- **204行目**: showErrorステート - スタックトレース表示切り替え
- **206-207行目**: エラータイプの判定（showSimpleRender、isLazyLoadError）
- **210-249行目**: Modalコンポーネントでラップ、isDismissable={false}

#### Step 4: エラータイプ別レンダリングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | FatalError.tsx | `packages/desktop-client/src/components/FatalError.tsx` | RenderSimple（32-108行目）、RenderLazyLoadError（110-130行目）、RenderUIError（132-149行目） |

**主要処理フロー（RenderSimple）**:
- **35-46行目**: IDBFailure判定とメッセージ
- **47-69行目**: SharedArrayBufferMissing判定とメッセージ
- **70-81行目**: その他の初期化エラーメッセージ

#### Step 5: SharedArrayBuffer回避オプションを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | FatalError.tsx | `packages/desktop-client/src/components/FatalError.tsx` | SharedArrayBufferOverrideコンポーネント（151-196行目） |

**主要処理フロー**:
- **152-153行目**: ステート定義（expanded、understand）
- **155-186行目**: 展開時のUI - 警告文、チェックボックス、ボタン
- **179-182行目**: LocalStorageへの保存とリロード処理
- **187-195行目**: 折りたたみ時のリンク表示

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

```
App
 │
 ├─ ErrorBoundary (FallbackComponent={ErrorFallback})
 │      │
 │      └─ ErrorFallback
 │             ├─ AppBackground
 │             └─ FatalError
 │                    │
 │                    ├─ エラータイプ判定
 │                    │      ├─ isLazyLoadError → RenderLazyLoadError
 │                    │      ├─ showSimpleRender → RenderSimple
 │                    │      │      ├─ IDBFailure → IndexedDBエラーメッセージ
 │                    │      │      ├─ SharedArrayBufferMissing → SABエラーメッセージ
 │                    │      │      │      └─ SharedArrayBufferOverride
 │                    │      │      └─ その他 → 汎用エラーメッセージ
 │                    │      └─ デフォルト → RenderUIError
 │                    │
 │                    ├─ Restart appボタン
 │                    │      └─ window.Actual.relaunch()
 │                    │
 │                    └─ Show Error
 │                           └─ error.stack表示
 │
 └─ ErrorBoundary (FallbackComponent={FatalError})
        └─ Modals
```

### データフロー図

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

例外発生 ───▶ ErrorBoundary.componentDidCatch() ───▶ FallbackComponent呼び出し
                          │
                          ▼
                    FatalError(error)
                          │
                    エラータイプ判定
                          │
         ┌────────────────┼────────────────┐
         ▼                ▼                ▼
   LazyLoadError    app-init-failure    UIError
         │                │                │
         ▼                ▼                ▼
RenderLazyLoadError  RenderSimple    RenderUIError
         │                │                │
         └────────────────┼────────────────┘
                          │
                          ▼
                    Modal表示
                          │
     ┌────────────────────┼────────────────────┐
     ▼                    ▼                    ▼
Restart押下          Show Error押下     Advanced options
     │                    │                    │
     ▼                    ▼                    ▼
window.Actual      error.stack表示    LocalStorage設定
.relaunch()                            + リロード
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| FatalError.tsx | `packages/desktop-client/src/components/FatalError.tsx` | ソース | メインエラー表示コンポーネント |
| App.tsx | `packages/desktop-client/src/components/App.tsx` | ソース | ErrorBoundary設定、ErrorFallback定義 |
| errors.ts | `packages/loot-core/src/shared/errors.ts` | ソース | LazyLoadFailedErrorクラス定義 |
| Modal.tsx | `packages/desktop-client/src/components/common/Modal.tsx` | ソース | モーダルコンポーネント |
| Link.tsx | `packages/desktop-client/src/components/common/Link.tsx` | ソース | 外部リンクコンポーネント |
| LoadComponent.tsx | `packages/desktop-client/src/components/util/LoadComponent.tsx` | ソース | 遅延読み込みコンポーネント（LazyLoadFailedError発生元） |
| AppBackground.tsx | `packages/desktop-client/src/components/AppBackground.tsx` | ソース | エラー時の背景表示 |
