# 通知設計書 31-display_errorエラー

## 概要

本ドキュメントは、Julia REPL の対話型評価ループ (`eval_user_input`) において、`display_error` 関数自体がエラーを引き起こした場合に出力されるシステムエラー通知の設計を記述する。

### 本通知の処理概要

本通知は、Julia の REPL で式を評価した際に発生したエラーを表示する `display_error` 関数が、さらに二次的なエラーを起こした場合にシステムレベルのエラーメッセージをログに記録する処理である。

**業務上の目的・背景**：Julia の REPL はユーザーの入力式を評価し、エラーが発生した場合は `display_error` でスタックトレースを表示する。しかし、`display_error` 自体が何らかの理由（表示メソッドの不具合、IO の故障など）でエラーを起こすことがある。この通知は、そのような二次障害の連鎖を開発者やユーザーに知らせ、デバッグを支援する目的で設けられている。

**通知の送信タイミング**：`eval_user_input` 関数内の `while true` ループにおいて、`lasterr` を表示する `invokelatest(display_error, errio, lasterr)` の呼び出し中にエラーがキャッチされ、かつ `errcount > 0`（1回以上のエラー表示失敗が既に発生）の場合に送信される。具体的には `base/client.jl` の161行目で発火する。

**通知の受信者**：Julia プロセスの標準エラー出力 (stderr) を監視する開発者・運用者。ログレベルは `Error` であり、Julia のログシステム（`@error` マクロ）を通じて出力される。

**通知内容の概要**：`"SYSTEM: display_error(errio, lasterr) caused an error"` というメッセージが出力される。このメッセージは、エラー表示関数自体が障害を起こしたことを示す。

**期待されるアクション**：受信者は、Julia の REPL 表示処理に問題があることを認識し、カスタム display メソッドや IO ストリームの状態を確認する。この通知の後に `errcount > 2` に達すると致命的エラー通知（No.32）が発生し、REPL ループが中断される。

## 通知種別

ログ（Error） -- Julia の標準ログシステム（`@error` マクロ）による stderr へのエラーレベル出力

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（`@error` マクロによる即座のログ出力） |
| 優先度 | 高 |
| リトライ | 無し |

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

Julia の標準ログシステムにより、現在アクティブなログハンドラ（デフォルトでは `ConsoleLogger`）に送信される。REPL 環境では stderr に直接出力される。送信先の動的な決定はなく、プロセス起動時に構成されたログハンドラに従う。

## 通知テンプレート

### メール通知の場合

該当なし（本通知はログ出力であり、メール送信は行わない）

### 本文テンプレート

```
SYSTEM: display_error(errio, lasterr) caused an error
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| （なし） | 本通知は固定文字列のみ | -- | -- |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| REPL評価ループ | `display_error` の呼び出し中にエラーが発生 | `errcount > 0`（過去にエラー表示失敗が1回以上あった） | `eval_user_input` 内の `catch` ブロックで検出 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| `errcount == 0` | 初回のエラーでは本通知は発生しない（初回は単に `lasterr` を更新するのみ） |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[eval_user_input: 式の評価] --> B{lasterr が存在するか}
    B -->|Yes| C[display_error でエラー表示を試行]
    B -->|No| D[式を評価し結果を表示]
    C --> E{display_error が成功したか}
    E -->|成功| F[errcount = 0, lasterr = nothing]
    E -->|失敗 catch| G{errcount > 0 か}
    G -->|Yes| H["@error SYSTEM: display_error caused an error"]
    G -->|No| I[errcount += 1, lasterr を更新]
    H --> I
    I --> J{errcount > 2 か}
    J -->|Yes| K[致命的エラー通知 No.32 を発生させループ終了]
    J -->|No| A
    D --> L{表示中にエラー発生}
    L -->|No| M[終了]
    L -->|Yes| N["@error Evaluation succeeded but display error"]
```

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

### 参照テーブル一覧

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

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| display_error の二次エラー | `display_error` 関数がエラーをスロー | `errcount` をインクリメントし、`lasterr` を更新してリトライ |
| 致命的エラー | `errcount > 2` に到達 | REPL 評価ループを `break` で終了 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 最大2回（errcount が 3 に達すると打ち切り） |
| リトライ間隔 | 即時（同一ループ内で再試行） |
| リトライ対象エラー | `display_error` のすべてのエラー |

## 配信設定

### レート制限

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

### 配信時間帯

制限なし（REPL 操作中に随時発生し得る）

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

本通知は固定メッセージのみを出力し、ユーザーデータや機密情報は含まない。ただし、後続のスタックトレースにはファイルパスやソースコード行番号が含まれる場合がある。

## 備考

- 本通知（No.31）は、致命的エラー通知（No.32）の前段階として発生する。errcount が蓄積して 2 を超えると No.32 が発火する。
- No.30「表示エラー通知」とは異なり、No.30 は `display(value)` の失敗時に発生し、本通知は `display_error` の失敗時に発生する。

---

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

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

### 推奨読解順序

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

REPL 評価ループで扱われるエラー情報のデータ構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | client.jl | `base/client.jl` | `ExceptionStack` 型と `scrub_repl_backtrace` 関数（92-102行目）によるバックトレース加工を理解する |

**読解のコツ**: `ExceptionStack` は `NamedTuple` の配列であり、各要素は `exception` と `backtrace` フィールドを持つ。`scrub_repl_backtrace` は REPL 内部フレームをスタックトレースから除去する。

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

REPL 評価ループ全体の流れを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | client.jl | `base/client.jl` | `eval_user_input` 関数（127-174行目）が本通知のエントリーポイント |

**主要処理フロー**:
1. **127行目**: `eval_user_input` 関数の定義開始。`errio`, `ast`, `show_value` を引数に取る
2. **128-129行目**: `errcount = 0`, `lasterr = nothing` で初期化
3. **131行目**: `while true` による評価ループ開始
4. **136-141行目**: `lasterr` が存在する場合、`display_error` を呼び出し
5. **142-156行目**: `lasterr` が `nothing` の場合、式を評価して結果を表示
6. **159-169行目**: `catch` ブロック -- ここで本通知が発火する

#### Step 3: 通知発火ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | client.jl | `base/client.jl` | `catch` ブロック内の `errcount` 制御（159-169行目）が本通知の核心 |

**主要処理フロー**:
- **160-162行目**: `errcount > 0` の場合に `@error "SYSTEM: display_error(errio, lasterr) caused an error"` を発行
- **163行目**: `errcount += 1`
- **164行目**: 現在の例外スタックを `lasterr` に保存
- **166-168行目**: `errcount > 2` で致命的エラー通知を発行しループ離脱

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

```
_start() [base/client.jl:575]
    |
    +-- exec_options() [base/client.jl:234]
    |       |
    |       +-- run_main_repl() [base/client.jl:515]
    |               |
    |               +-- run_std_repl() / run_fallback_repl()
    |                       |
    |                       +-- eval_user_input() [base/client.jl:127]
    |                               |
    |                               +-- invokelatest(display_error, errio, lasterr) [行139]
    |                               |       (ここでエラー発生時)
    |                               +-- @error "SYSTEM: display_error..." [行161]
    |                               +-- @error "It is likely..." [行167] (errcount > 2 時)
```

### データフロー図

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

ユーザー入力式 -------> eval_user_input()
                            |
                            +-- 式評価 (Core.eval)
                            |       |
                            |       +-- エラー発生 --> lasterr に保存
                            |
                            +-- display_error(lasterr)
                            |       |
                            |       +-- 二次エラー発生 --> catch
                            |                               |
                            |                               +-- errcount チェック
                            |                                       |
                            |                                       +--> @error ログ --> stderr
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| client.jl | `base/client.jl` | ソース | REPL フロントエンド処理、`eval_user_input` 関数の定義 |
| logging.jl | `base/logging.jl` | ソース | `@error` マクロの定義と Julia ログシステムの基盤 |
| errorshow.jl | `base/errorshow.jl` | ソース | `display_error` が内部で使用する `showerror` / `show_exception_stack` の定義 |
