# 通知設計書 7-ランタイムエラー通知

## 概要

本ドキュメントは、Vue.jsランタイムにおけるエラーハンドリング・通知機構の設計仕様を記述する。`packages/runtime-core/src/errorHandling.ts`に実装されており、コンポーネントのライフサイクル、レンダリング、ウォッチャー等で発生したエラーをコンポーネントツリーを辿って`errorCaptured`フック、`app.config.errorHandler`の順に伝播する。最終的に`console.error`または`throw`で通知する。

### 本通知の処理概要

この通知は、Vueランタイムで発生するあらゆるエラーを統一的にハンドリングする仕組みである。エラーはコンポーネントツリーを辿って伝播し、各レベルで捕捉・処理が可能な多層的なエラーハンドリングを提供する。

**業務上の目的・背景**：Vueアプリケーションでは、コンポーネントのsetup関数、レンダリング関数、ライフサイクルフック、ウォッチャー、イベントハンドラなど多岐にわたるコンテキストでエラーが発生しうる。これらのエラーを統一的に捕捉・処理する仕組みが必要である。本機構は、エラーの発生コンテキスト情報（ErrorTypeStringsで16種類以上のエラーコンテキストを定義）を付与し、コンポーネントツリーを辿るバブリング型のエラー伝播を実現する。これにより、任意の階層でのエラー捕捉が可能となり、アプリケーション全体のエラー監視やリカバリーが容易になる。

**通知の送信タイミング**：ユーザーコードの実行中にエラーが発生した場合に即座に発火する。`callWithErrorHandling`（同期）および`callWithAsyncErrorHandling`（非同期Promise）を通じてエラーが捕捉される。

**通知の受信者**：まずコンポーネントツリー上の`errorCaptured`フック、次にアプリレベルの`app.config.errorHandler`、最終的に開発者コンソール（`console.error`）または例外としてthrowされる。

**通知内容の概要**：エラーオブジェクト、エラーが発生したコンポーネントのプロキシインスタンス、エラーコンテキスト情報（`ErrorTypeStrings`の文字列、または本番環境ではVue公式URLリンク）が通知される。

**期待されるアクション**：`errorCaptured`フックでのエラーリカバリー、`app.config.errorHandler`での集中エラーハンドリング（外部監視サービスへの送信等）、または開発者によるデバッグ・修正。

## 通知種別

エラーハンドリング（`errorCaptured`フック / `app.config.errorHandler` / `console.error` / `throw`）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（callWithErrorHandling）/ 非同期対応（callWithAsyncErrorHandling） |
| 優先度 | 高 |
| リトライ | なし |

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

エラーは以下の優先順位で伝播する：

1. **errorCapturedフック**：エラーが発生したコンポーネントから親方向にツリーを辿り、各コンポーネントの`errorCaptured`フック（`cur.ec`）を呼び出す。フックが`false`を返した場合、伝播を停止する。
2. **app.config.errorHandler**：アプリレベルのグローバルエラーハンドラ。設定されている場合はここで処理が完了し、logErrorは呼ばれない。
3. **logError**：上記のいずれでも処理されなかった場合の最終処理。
   - 開発モード（`__DEV__`）：`warn()`で警告を出力後、`throwInDev`がtrueならthrow、falseならconsole.error
   - 本番モード：`throwUnhandledErrorInProduction`がtrueならthrow、falseならconsole.error

## 通知テンプレート

### コンソール出力の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | N/A |
| 送信元名称 | `[Vue warn]`（開発モードのwarn出力時） |
| 件名 | N/A |
| 形式 | テキスト + エラーオブジェクト |

### 本文テンプレート

開発モードの場合：
```
[Vue warn]: Unhandled error during execution of {エラーコンテキスト名}
  at <{コンポーネント名}>
{エラーオブジェクト}     ← throw or console.error
```

本番モードの場合：
```
{エラーオブジェクト}     ← console.error or throw
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| N/A | N/A | N/A | コンソール出力のため添付ファイルなし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| err | エラーオブジェクト | try-catchで捕捉 | Yes |
| instance | エラー発生元のコンポーネントインスタンス | callWithErrorHandlingの引数 | No |
| type | エラーコンテキスト（ErrorTypes） | callWithErrorHandlingの引数 | Yes |
| errorInfo | エラーコンテキスト文字列 | ErrorTypeStrings[type]（開発モード）またはVue公式URL（本番） | Yes |
| exposedInstance | 公開用プロキシインスタンス | instance.proxy | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 同期エラー | callWithErrorHandling内のtry-catch | 関数実行中にエラー発生 | setup、render、ライフサイクルフック等 |
| 非同期エラー | callWithAsyncErrorHandling内のPromise.catch | 非同期関数のPromise rejected | 非同期setup、非同期イベントハンドラ等 |
| 直接呼び出し | handleError()直接呼び出し | エラー発生時 | フレームワーク内部からの直接呼び出し |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| errorCapturedフックがfalseを返した場合 | エラー伝播が停止し、以降のハンドラは呼ばれない |
| app.config.errorHandlerが設定されている場合 | logErrorは呼ばれない（errorHandlerで処理完了） |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[エラー発生] --> B[handleError呼び出し]
    B --> C{instanceが存在するか?}
    C -->|Yes| D[コンポーネントツリーを親方向に走査]
    D --> E{errorCapturedフック<br>ec が存在するか?}
    E -->|Yes| F[errorCapturedフック実行]
    F --> G{falseが返されたか?}
    G -->|Yes| H[伝播停止 → return]
    G -->|No| I[次の親へ]
    E -->|No| I
    I --> J{親が存在するか?}
    J -->|Yes| D
    J -->|No| K{app.config.errorHandler<br>が設定されているか?}
    K -->|Yes| L[errorHandler呼び出し<br>pauseTracking/resetTracking付き]
    L --> M[return]
    K -->|No| N[logError呼び出し]
    C -->|No| N
    N --> O{__DEV__?}
    O -->|Yes| P[warn: Unhandled error...を出力]
    P --> Q{throwInDev?}
    Q -->|Yes| R[throw err]
    Q -->|No| S[console.error]
    O -->|No| T{throwInProd?}
    T -->|Yes| R
    T -->|No| S
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| N/A | N/A | データベースは使用しない |

### テーブル別参照項目詳細

本通知はデータベースを使用しない。以下のインメモリデータ構造を参照する。

| 参照データ | 用途 | 取得方法 |
|-----------|------|---------|
| instance.parent | 親コンポーネントへの参照（ツリー走査用） | ComponentInternalInstance |
| cur.ec | errorCapturedフックの配列 | コンポーネントインスタンスのecプロパティ |
| instance.appContext.config.errorHandler | アプリレベルエラーハンドラ | appContextから取得 |
| instance.appContext.config.throwUnhandledErrorInProduction | 本番環境でのthrow設定 | appContextから取得 |
| ErrorTypeStrings | エラーコンテキスト名のマッピング | errorHandling.ts L34-66 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| N/A | N/A | データベースの更新は行わない |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| errorHandler内のエラー | app.config.errorHandler内で例外発生 | callWithErrorHandling経由で安全に呼び出すため、errorHandler自体のエラーも捕捉される |
| errorCapturedフック内のエラー | フック内で例外発生 | callWithErrorHandling経由のため自動的に上位に伝播 |
| 非同期エラー | Promise rejected | Promise.catchでhandleErrorに伝播 |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

制限なし。

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

- エラーオブジェクトにスタックトレースが含まれるため、外部サービスへの送信時は注意が必要
- `exposedInstance`（instance.proxy）がerrorHandlerに渡されるため、コンポーネントの内部状態にアクセス可能
- 本番モードではエラーコンテキストがURLリンクに置換され、詳細メッセージの露出が防止される

## 備考

- `ErrorCodes`として16種類のランタイムエラーコンテキストが定義されている（SETUP_FUNCTION〜APP_UNMOUNT_CLEANUP）
- WatchErrorCodes（WATCH_GETTER、WATCH_CALLBACK、WATCH_CLEANUP）はreactivityパッケージに移動されたが、ErrorCodes enumの値との互換性が維持されている
- `callWithAsyncErrorHandling`は配列の関数も受け入れ、各関数を順次実行する
- `throwInDev`パラメータ（デフォルトtrue）により、開発モードでのthrow動作を制御可能
- `throwUnhandledErrorInProduction`はappContext.configで設定可能な本番環境でのthrow制御フラグ
- `pauseTracking`/`resetTracking`でerrorHandler呼び出し中のリアクティブ追跡を一時停止する

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | errorHandling.ts | `packages/runtime-core/src/errorHandling.ts` | L11-32: ErrorCodes enum（16種類のランタイムエラーコンテキスト） |
| 1-2 | errorHandling.ts | `packages/runtime-core/src/errorHandling.ts` | L34-66: ErrorTypeStrings（各エラーコードに対応する人間可読な文字列） |
| 1-3 | errorHandling.ts | `packages/runtime-core/src/errorHandling.ts` | L68: ErrorTypes型（LifecycleHooks | ErrorCodes | WatchErrorCodes の合併型） |

**読解のコツ**: ErrorCodesの値にはギャップがある（NATIVE_EVENT_HANDLER = 5から始まる）。これはWatchErrorCodes（2,3,4）がreactivityパッケージに移動された名残であり、互換性維持のため値が保持されている。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | errorHandling.ts | `packages/runtime-core/src/errorHandling.ts` | L70-81: callWithErrorHandling（同期エラーハンドリング） |
| 2-2 | errorHandling.ts | `packages/runtime-core/src/errorHandling.ts` | L83-110: callWithAsyncErrorHandling（非同期エラーハンドリング、配列対応） |

**主要処理フロー**:
1. **L76-77**: `try { args ? fn(...args) : fn() }` - 関数を実行
2. **L78-79**: `catch (err) { handleError(err, instance, type) }` - エラーをhandleErrorに委譲
3. **L91**: 非同期の場合、`res.catch(err => handleError(...))` でPromise.catchを設定
4. **L99-103**: 配列の場合、各関数を順次`callWithAsyncErrorHandling`で実行

#### Step 3: エラー伝播メカニズムを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | errorHandling.ts | `packages/runtime-core/src/errorHandling.ts` | L112-155: handleError関数。エラー伝播の中核ロジック |
| 3-2 | errorHandling.ts | `packages/runtime-core/src/errorHandling.ts` | L157-185: logError関数。最終的なエラー出力 |

**主要処理フロー**:
- **L122-141**: コンポーネントツリーを親方向に走査し、errorCaptured（`cur.ec`）フックを順次呼び出す
- **L134**: `errorCapturedHooks[i](...) === false` でfalseが返されたら伝播停止
- **L143-152**: app.config.errorHandlerが設定されていれば、pauseTracking付きで呼び出し
- **L154**: 上記いずれでも処理されなければlogErrorを呼び出し
- **L164-178**: logErrorでは`__DEV__`に応じてwarn + throw/console.error、本番ではthrow/console.error

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

```
callWithErrorHandling(fn, instance, type, args)  [errorHandling.ts:70]
    |
    +-- fn(...args)                               [ユーザーコード実行]
    |
    +-- [エラー発生時]
            |
            +-- handleError(err, instance, type)  [errorHandling.ts:112]
                    |
                    +-- errorCapturedフック走査     [L122-141]
                    |       |
                    |       +-- cur.ec[i](err, exposedInstance, errorInfo)
                    |       +-- [false返却で伝播停止]
                    |
                    +-- app.config.errorHandler    [L143-152]
                    |       |
                    |       +-- pauseTracking()
                    |       +-- callWithErrorHandling(errorHandler, ...)
                    |       +-- resetTracking()
                    |
                    +-- logError(err, type, ...)   [errorHandling.ts:157]
                            |
                            +-- [__DEV__]
                            |       +-- warn("Unhandled error...")
                            |       +-- throw err / console.error(err)
                            |
                            +-- [本番]
                                    +-- throw err / console.error(err)
```

### データフロー図

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

err (unknown)              +-- handleError()                   +-- errorCapturedフック
  |                        |     |                             |     (コンポーネント単位)
instance                   |     +-- ツリー走査                |
  (ComponentInternal)  --->|     +-- errorCaptured呼び出し ---->+-- errorHandler
  |                        |     +-- errorHandler呼び出し      |     (アプリ単位)
type (ErrorTypes)          |     +-- logError()                |
  |                        |                                   +-- console.error / throw
errorInfo (string)    ---->+--                                      (最終出力)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| errorHandling.ts | `packages/runtime-core/src/errorHandling.ts` | ソース | エラーハンドリング全体（callWithErrorHandling, callWithAsyncErrorHandling, handleError, logError） |
| warning.ts | `packages/runtime-core/src/warning.ts` | ソース | warn関数、pushWarningContext/popWarningContext |
| enums.ts | `packages/runtime-core/src/enums.ts` | ソース | LifecycleHooks enum定義 |
| effect.ts | `packages/reactivity/src/effect.ts` | ソース | pauseTracking/resetTracking、WatchErrorCodes |
| apiCreateApp.ts | `packages/runtime-core/src/apiCreateApp.ts` | ソース | AppConfig.errorHandler定義 |
