# 通知設計書 25-ヒントハンドラエラー

## 概要

本ドキュメントは、Juliaのエラーヒントシステムにおいて、登録されたヒントハンドラがエラーを起こした場合に出力されるエラー通知の設計を記述する。

### 本通知の処理概要

本通知は、`Base.Experimental.show_error_hints` 関数内で、登録されたヒントハンドラ（`register_error_hint` で登録された関数）が例外をスローした場合に出力されるエラーログである。

**業務上の目的・背景**：Juliaのエラーヒントシステム（`Base.Experimental.register_error_hint`）は、パッケージがエラーメッセージに有用なヒントを追加するための拡張機構を提供する。ヒントハンドラは外部パッケージによって登録されるため、そのハンドラ自体がバグを含む可能性がある。ハンドラのエラーがエラー表示全体を壊さないよう、ハンドラのエラーは個別にキャッチされてエラーログとして出力される。

**通知の送信タイミング**：エラー表示中に `show_error_hints` が呼ばれ、登録されたヒントハンドラの `@invokelatest handler(io, ex, args...)` 呼び出しが例外をスローした場合に発生する。

**通知の受信者**：ヒントハンドラを登録したパッケージの開発者。コンソール（stderr）に表示される。

**通知内容の概要**：エラーを起こしたハンドラの名前、対象の例外型、ハンドラが定義されたモジュール、および例外のスタック情報を表示する。

**期待されるアクション**：パッケージ開発者はヒントハンドラの実装を修正する。

## 通知種別

ログ（Error） -- Julia標準ロギングフレームワーク（`@error` マクロ）によるコンソール出力

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（エラー表示処理中に即時出力） |
| 優先度 | 高（ログレベル Error） |
| リトライ | 無し |

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

Julia の標準ロギングフレームワークに従い、`stderr` に出力される。

## 通知テンプレート

### メール通知の場合

該当なし（コンソールログ出力）

### 本文テンプレート

```
┌ Error: Hint-handler {handler} for {ex_supertype} in {module} caused an error
│   exception =
│    {nested exception stack}
└ @ Base.Experimental experimental.jl:329
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| handler | エラーを起こしたヒントハンドラ関数 | `show_error_hints` のループ内変数 | Yes |
| ex_supertype | 現在処理中の例外のスーパータイプ | `typeof(ex)` から型階層を走査中の現在の型 | Yes |
| module (`tn.module`) | ハンドラが定義されたモジュール | `typeof(handler).name.module` | Yes |
| exception | 捕捉された例外情報 | `current_exceptions()` | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| エラー表示 | `show_error_hints` 内でのハンドラ呼び出し | `@invokelatest handler(io, ex, args...)` が例外をスロー | ハンドラ実行中の例外発生時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| `ex isa exct` が false | ハンドラの対象例外型と一致しない場合、ハンドラ自体がスキップされる |
| ハンドラが正常終了 | catch ブロックに入らないため通知なし |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[showerror 呼び出し] --> B["show_error_hints(io, ex, args...)"]
    B --> C["typeof(ex) から型階層を走査"]
    C --> D["ex_supertype の _hint_handlers を取得"]
    D --> E["登録済みハンドラをイテレーション"]
    E --> F{"ex isa exct?"}
    F -->|No| E
    F -->|Yes| G["try: @invokelatest handler(io, ex, args...)"]
    G --> H{"例外発生?"}
    H -->|No| E
    H -->|Yes| I["@error 出力"]
    I --> E
```

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

### 参照テーブル一覧

| データ構造 | 参照先 | 参照目的 |
|----------|--------|---------|
| `_hint_handlers` | `IdDict{Core.TypeName, Vector{Any}}` | 例外型ごとのヒントハンドラリスト |

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| ハンドラ例外 | ヒントハンドラが任意の例外をスロー | `@error` ログを出力し、次のハンドラの処理に移行 |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 制限 | なし（エラー表示ごとにハンドラが呼ばれる度に発生し得る） |

### 配信時間帯

制限なし

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

ハンドラの名前とモジュール名がログに含まれる。外部パッケージのハンドラ情報が露出するが、これはデバッグ目的の情報であり、一般的に機密性はない。`current_exceptions()` によるネストされた例外スタックが出力されるため、内部状態の一部が露出する可能性がある。

## 備考

- ヒントハンドラシステムは `Base.Experimental` に属する実験的APIである
- `@invokelatest` を使用してハンドラを呼び出しており、最新のワールドエイジで実行される
- ハンドラのエラーは `catch` でベアキャッチ（型指定なし）されるため、すべての例外がキャッチされる
- `MethodError` には特別なシグネチャ `handler(io, exc::MethodError, argtypes, kwargs)` が使用される
- 型階層を上方に走査するため、具象型のハンドラだけでなく、スーパータイプのハンドラも呼び出される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | experimental.jl | `base/experimental.jl` | 303行目: `_hint_handlers` の定義。`IdDict{Core.TypeName, Vector{Any}}` |
| 1-2 | experimental.jl | `base/experimental.jl` | 297-301行目: `register_error_hint` 関数。ハンドラの登録メカニズム |

**読解のコツ**: `_hint_handlers` は `Core.TypeName` をキーとする辞書。これにより、例外型のスーパータイプも含めてハンドラを検索できる。各エントリは `(exct, handler)` のタプルのリスト。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | experimental.jl | `base/experimental.jl` | 317-334行目: `show_error_hints` 関数。ヒント表示の起点 |
| 2-2 | errorshow.jl | `base/errorshow.jl` | 397行目: `showerror` 内での `Experimental.show_error_hints` 呼び出し |

#### Step 3: 通知発生箇所を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | experimental.jl | `base/experimental.jl` | 324-330行目: try-catch ブロック。329行目に `@error` |

**主要処理フロー**:
- **319行目**: `typeof(ex)` で例外の型を取得
- **320行目**: `while` ループで型階層を上方に走査（`Any` まで）
- **321行目**: `get(_hint_handlers, Core.typename(ex_supertype), Any[])` でハンドラリスト取得
- **322行目**: ハンドラリストをイテレーション
- **323行目**: `ex isa exct` で対象例外型のチェック
- **326行目**: `@invokelatest handler(io, ex, args...)` でハンドラ呼び出し
- **327行目**: `catch` でエラーをキャッチ
- **328行目**: `typeof(handler).name` でハンドラの型名情報取得
- **329行目**: `@error "Hint-handler $handler for $(ex_supertype) in $(tn.module) caused an error"` 出力

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

```
showerror(io, ex) [errorshow.jl]
    │
    └─ Experimental.show_error_hints(io, ex, args...) [experimental.jl:317]
           │
           ├─ typeof(ex) -> ex_supertype [experimental.jl:319]
           │
           ├─ while ex_supertype != Any [experimental.jl:320]
           │      │
           │      ├─ get(_hint_handlers, ...) [experimental.jl:321]
           │      │
           │      ├─ for (exct, handler) in hinters [experimental.jl:322]
           │      │      │
           │      │      ├─ @invokelatest handler(...) [experimental.jl:326]
           │      │      │
           │      │      └─ @error "Hint-handler..." [experimental.jl:329]
           │      │
           │      └─ supertype(ex_supertype) [experimental.jl:332]
           │
           └─ register_error_hint(handler, exct) [experimental.jl:297]
                  └─ push!(_hint_handlers[typename], (exct, handler))
```

### データフロー図

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

_hint_handlers ──────────────▶ ハンドラリスト取得
                              │
例外オブジェクト (ex) ────────▶ 型階層走査 ──────▶ ハンドラ呼び出し
                              │                  │
io (出力先) ─────────────────▶ ├─ 正常 ──────────▶ ヒントテキスト ──▶ io
                              │
                              └─ 例外発生 ───────▶ @error ──────────▶ stderr
                                   │
                                   ├─ handler名
                                   ├─ ex_supertype名
                                   ├─ module名
                                   └─ current_exceptions()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| experimental.jl | `base/experimental.jl` | ソース | 通知の発生元。`register_error_hint`, `show_error_hints`, `_hint_handlers` の実装 |
| errorshow.jl | `base/errorshow.jl` | ソース | `showerror` からの `show_error_hints` 呼び出し箇所 |
| logging.jl | `base/logging/logging.jl` | ソース | `@error` マクロの実装 |
