# 通知設計書 13-Unable to read file

## 概要

本ドキュメントは、Prettier CLI においてファイル読み込みに失敗した場合に表示されるエラー通知「Unable to read file」について定義する設計書である。

### 本通知の処理概要

Prettier CLI がフォーマット対象ファイルを読み込もうとした際に、ファイルアクセス権限の問題、ファイルの不在、またはその他のI/Oエラーにより読み込みに失敗した場合、ユーザーに対してエラー内容を通知する。この通知により、ユーザーはどのファイルの読み込みに失敗したか、およびその原因を把握できる。

**業務上の目的・背景**：開発者がコードフォーマットを実行する際、対象ファイルの読み込みが成功することは処理の前提条件である。ファイルシステムの問題（権限不足、ファイル削除、ディスクエラー等）が発生した場合、ユーザーに明確なエラーメッセージを提供することで、問題の特定と解決を支援する。これはCI/CDパイプラインでのエラー診断や、共有ファイルシステム環境での問題解決に特に重要である。

**通知の送信タイミング**：`prettier` コマンドを実行し、対象ファイルを `fs.readFile()` で読み込もうとした際にエラーが発生した時点で即座に通知される。具体的には、`format.js` の `formatFiles` 関数内の `try-catch` ブロックでエラーがキャッチされた時点で出力される（行341-357）。

**通知の受信者**：CLI を実行している開発者またはCI/CDシステム。標準エラー出力（stderr）に出力されるため、ターミナルで実行している場合はリアルタイムで表示され、パイプライン実行時はエラーログとして記録される。

**通知内容の概要**：「Unable to read file」という固定メッセージ、読み込みに失敗したファイル名、およびエラーの詳細メッセージ（Node.jsのエラーオブジェクトの `message` プロパティ）で構成される。

**期待されるアクション**：この通知を受け取った場合、ユーザーは以下のアクションを検討する必要がある。(1) ファイルが存在するか確認、(2) ファイルの読み取り権限を確認、(3) ファイルが別のプロセスにロックされていないか確認、(4) ファイルパスが正しいか確認。

## 通知種別

CLI 標準エラー出力（エラー通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（ファイル読み込みエラー発生時に即座に出力） |
| 優先度 | 高（エラー通知） |
| リトライ | なし（一度きりの出力、ただし処理は継続） |

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

CLI 実行環境の標準エラー出力（`process.stderr`）に対して直接出力する。ログレベルが `error` 以上に設定されている場合のみ出力される（デフォルトで有効）。

## 通知テンプレート

### CLI出力通知の場合

| 項目 | 内容 |
|-----|------|
| 出力先 | 標準エラー出力（stderr） |
| 形式 | テキスト |
| カラー | プレフィックス `[error]` は赤色（picocolors.red） |

### 本文テンプレート

```
[error] Unable to read file "{ファイル名}":
{エラーメッセージ}
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| fileNameToDisplay | 表示用ファイル名（現在の作業ディレクトリからの相対パス） | `path.relative(cwd, filename)` をPOSIX形式に正規化 | Yes |
| error.message | エラー詳細メッセージ | Node.js `fs.readFile()` が投げるエラーオブジェクトの `message` プロパティ | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ファイル操作 | ファイル読み込み失敗 | `fs.readFile(filename, "utf8")` の実行時にエラーが発生した場合 | try-catch でキャッチされたエラー |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| ログレベルが `error` 未満 | `--log-level silent` 指定時は出力されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[formatFiles開始] --> B[ファイルパターン展開]
    B --> C[ファイルごとにループ]
    C --> D[fs.readFile実行]
    D -->|成功| E[フォーマット処理へ]
    D -->|失敗| F[エラーキャッチ]
    F --> G[空行出力]
    G --> H[context.logger.error出力]
    H --> I[process.exitCode = 2]
    I --> J[continue - 次のファイルへ]
    E --> K[終了]
    J --> C
```

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

### 参照テーブル一覧

本通知はデータベースを使用しない。ファイルシステムのみを参照する。

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| N/A | N/A | N/A |

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

該当なし

### 更新テーブル一覧

該当なし

#### 送信ログテーブル

本通知ではログテーブルへの記録は行わない。

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| ENOENT | ファイルが存在しない | ファイルパスを確認 |
| EACCES | 読み取り権限がない | ファイルの権限を確認・変更 |
| EISDIR | パスがディレクトリ | ファイルパスを確認 |
| EMFILE | ファイルハンドル上限到達 | 開いているファイルを閉じる |
| EIO | I/Oエラー | ディスクの状態を確認 |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

制限なし（CLI実行時に即座に出力）

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

- ファイル名とエラーメッセージがコンソールに出力されるため、機密性の高いファイル名やパスが含まれる場合は注意が必要
- エラーメッセージにはファイルシステムの構造情報が含まれる可能性がある
- 標準エラー出力への出力のみであり、ネットワーク送信は行わない

## 備考

- このエラーが発生しても処理は中断されず、次のファイルの処理に継続する
- `process.exitCode = 2` が設定され、処理完了後に終了コード2でプロセスが終了する
- c8（コードカバレッジツール）によるテストカバレッジ対象外のコードブロックである

---

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

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

### 推奨読解順序

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

Node.jsのファイルシステムエラーオブジェクトの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Node.js公式ドキュメント | - | `fs.readFile` の戻り値とエラーオブジェクト（code, message プロパティ） |

**読解のコツ**: Node.jsのファイルシステムエラーは `code`（例: ENOENT, EACCES）と `message`（人間可読なメッセージ）を持つ。

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

フォーマット処理のファイル読み込みロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | format.js | `src/cli/format.js` | ファイル読み込みとエラーハンドリング（行340-357） |

**主要処理フロー**:
1. **行340**: `input` 変数の宣言
2. **行341-342**: `try` ブロック開始、`fs.readFile(filename, "utf8")` の実行
3. **行343**: `catch (error)` でエラーをキャッチ
4. **行346**: 空行を出力（ファイル名プレビューとの区切り）
5. **行348-350**: エラーメッセージを `context.logger.error()` で出力
6. **行353**: `process.exitCode = 2` を設定
7. **行355**: `continue` で次のファイルの処理に移行

#### Step 3: ロガーの仕組みを理解する

エラーログ出力の実際の仕組みを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | logger.js | `src/cli/logger.js` | `error` メソッドの実装、カラー出力（赤色） |

**主要処理フロー**:
- **行25**: `error: createLogFunc("error", "red")` でエラーロガーを作成
- **行35**: `error` メソッドは `stderr` に出力
- **行37**: プレフィックス `[error]` が赤色で付与される

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

```
src/cli/format.js::formatFiles()  [行272]
    │
    ├─ expandPatterns()  [src/cli/expand-patterns.js]
    │      └─ ファイルパターンの展開
    │
    └─ ファイルループ [行305-466]
           │
           ├─ fs.readFile(filename, "utf8")  [行342]
           │      │
           │      └─ [エラー発生時]
           │             │
           │             ├─ context.logger.log("")  [行346]
           │             │      └─ 空行出力
           │             │
           │             ├─ context.logger.error()  [行348-350]
           │             │      │
           │             │      └─ "Unable to read file..." 出力
           │             │
           │             └─ process.exitCode = 2  [行353]
           │
           └─ continue  [行355]
                  └─ 次のファイルへ
```

### データフロー図

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

ファイルパス ───────────▶ fs.readFile()
                                │
                                ▼
                         [エラー発生]
                                │
                                ├─ error.message 取得
                                │
                                ▼
                         context.logger.error()
                                │
                                ▼
                         "[error] Unable to read file \"{ファイル名}\":
                          {エラーメッセージ}"
                                │
                                ▼
                         標準エラー出力 (stderr)
                                │
                                ▼
                         process.exitCode = 2
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| format.js | `src/cli/format.js` | ソース | フォーマット処理とファイル読み込みエラーハンドリング |
| logger.js | `src/cli/logger.js` | ソース | エラーログ出力機能（stderr、赤色プレフィックス） |
| utilities.js | `src/cli/utilities.js` | ソース | ユーティリティ関数（normalizeToPosix等） |
| index.js | `src/cli/index.js` | ソース | CLIエントリーポイント |
