第 9 章 エラー処理
9.1 エラー処理モデル
DTP 実装は「検出 - 通知 - 復旧」の三段階エラー処理モデルに従わ なければならない:
- 検出:異常状況を識別する。
- 通知:対端または上位層にエラー情報を送信する。
- 復旧:エラーの種類に応じて復旧措置を講じる。
実装はエラーを検出した際に、通知することなく黙ってフレームを破棄 してはならない。
9.2 エラーコード体系
DTP は以下のエラーコード体系を使用 しなければならない。エラーコードは非負整数で なければならず、機能モジュールごとに 8 つの範囲に区分される:
| 範囲 | カテゴリ | 処理戦略 |
|---|---|---|
| 1xxx | フレーム処理エラー | フレーム破棄 + 送信側に通知 |
| 2xxx | 暗号化エラー | フレーム破棄 + 送信側に通知 + 鍵再ネゴシエーションをトリガする可能性 |
| 3xxx | Agreement エラー | Fragment 破棄 + 送信側に通知 + 再ネゴシエーションをトリガする可能性 |
| 4xxx | DAG エラー | Fragment 拒否 + 送信側に通知、またはキャッシュして待機 |
| 5xxx | セッションエラー | セッション復旧を試みる + 失敗時にクローズして上位層に通知 |
| 6xxx | 再開エラー | 送信を一時停止 + 上位アプリケーションに通知 |
| 7xxx | バージョンエラー | バージョン非互換通知を送信 + ダウングレード処理を試みる |
| 8xxx | 権限エラー | 操作を拒否 + 要求側に通知 |
9.3 エラーコード定義
実装は以下の規範化されたエラーコード定義を使用 しなければならない。列挙されていないエラーコードを使用 してはならない。拡張が必要な場合、本仕様の後続バージョンで定義 しなければならない。
9.3.1 フレーム処理エラー(1xxx)
| エラーコード | 名称 | 発火条件 |
|---|---|---|
| 1001 | FRAME_DESERIALIZATION_FAILED | 受信したバイナリデータを LogicalFrame にデシリアライズできない |
| 1002 | FRAME_INVALID_FORMAT | LogicalFrame の構造が無効、または必須フィールドが欠落している |
9.3.2 暗号化エラー(2xxx)
| エラーコード | 名称 | 発火条件 |
|---|---|---|
| 2001 | DECRYPTION_FAILED | Payload の復号に失敗(誤った鍵またはデータ破損) |
| 2002 | KEY_NOT_READY | CAP 鍵交換が未完了であり、データ伝送を拒否する |
9.3.3 Agreement エラー(3xxx)
| エラーコード | 名称 | 発火条件 |
|---|---|---|
| 3001 | AGREEMENT_NOT_FOUND | Fragment が未知の Agreement_ID を参照している |
| 3002 | AGREEMENT_EXPIRED | 参照された Agreement が有効期限切れ(validityPeriod を超過) |
| 3003 | AGREEMENT_NEGOTIATION_FAILED | ネゴシエーションが完了できない(タイムアウト、対端の再ネゴシエーション拒否など) |
9.3.4 DAG エラー(4xxx)
| エラーコード | 名称 | 発火条件 |
|---|---|---|
| 4001 | DAG_CYCLE_DETECTED | Fragment を追加すると DAG 上に循環が形成される |
| 4002 | DAG_DEPENDENCY_UNRESOLVED | Fragment の依存がキャッシュタイムアウト内に解決されなかった |
9.3.5 セッションエラー(5xxx)
| エラーコード | 名称 | 発火条件 |
|---|---|---|
| 5001 | SESSION_NOT_FOUND | 参照された Session_ID が存在しない |
| 5002 | SESSION_TIMEOUT | セッションが非アクティブによりタイムアウト |
| 5003 | SESSION_RESTORE_FAILED | 再接続後のセッション復元に失敗 |
9.3.6 再開エラー(6xxx)
| エラーコード | 名称 | 発火条件 |
|---|---|---|
| 6001 | BUFFER_FULL | 送信側の未確認 Fragment キャッシュが容量上限に達した |
| 6002 | RETRANSMISSION_TIMEOUT | Fragment 再送がタイムアウトしても確認応答を受信できない(再送回数を使い切った) |
9.3.7 バージョンエラー(7xxx)
| エラーコード | 名称 | 発火条件 |
|---|---|---|
| 7001 | VERSION_INCOMPATIBLE | 受信フレームのプロトコルバージョン番号が自身のサポートバージョンより高い |
9.3.8 権限エラー(8xxx)
| エラーコード | 名称 | 発火条件 |
|---|---|---|
| 8001 | PERMISSION_DENIED | 現在のロールでは当該操作を実行できない |
| 8002 | OBSERVER_WRITE_DENIED | Observer が書き込み操作を試みた(Observer は読み取り専用) |
9.4 エラーコードの一意性
実装はエラーコードの一意性を保証 しなければならない:
- 各エラーコードは一意のエラータイプに対応 しなければならない。
- 異なるエラータイプが同一のエラーコードを共有 してはならない。
- 実装は本仕様で既に割り当て済みのエラーコードを再定義 してはならない。
9.5 エラー通知機構
9.5.1 ErrorNotificationFrame
エラー通知は ControlFrame を介して伝達 しなければならない。定義は以下の通り:
interface ErrorNotificationFrame {
frameType: "control";
controlType: "error_notification";
errorCode: DTPErrorCode;
errorMessage: string;
relatedFrameId?: FragmentID;
relatedAgreementId?: AgreementID;
details?: Record<string, unknown>;
}
| フィールド | 規範的要件 |
|---|---|
frameType | "control" で なければならない |
controlType | "error_notification" で なければならない |
errorCode | 第 9.3 節で定義されたエラーコードのいずれかで なければならない |
errorMessage | 人間が読めるエラー記述で なければならない。対端が理解できる言語を使用 すべきである |
relatedFrameId | 任意。エラーが特定のフレームによって発火された場合、当該フレームの fragmentId を含 まなければならない |
relatedAgreementId | 任意。エラーが特定の Agreement に関連する場合、Agreement_ID を含 まなければならない |
details | 任意。デバッグ用の追加情報を含 んでもよい |
9.5.2 エラー通知の伝送
ErrorNotificationFrame は通常の LogicalFrame チャネルを介して伝送 しなければならず、Payload を暗号化 しなければならない。
エラー自体が暗号化を不可能にする場合(例えば KEY_NOT_READY エラー)、実装は実装定義の帯域外チャネルを介してエラーを返 してもよい。ただし、暗号化チャネル内で平文によりエラーを送信 してはならない。
9.6 主要なエラー処理フロー
9.6.1 デシリアライズ失敗(1001)
受信した LogicalFrame をデシリアライズできない場合、受信側は以下を しなければならない:
- そのフレームを破棄する。
FRAME_DESERIALIZATION_FAILEDエラー通知を送信する。- デシリアライズ失敗を理由にセッションをクローズ してはならない。
9.6.2 復号失敗(2001)
受信した Payload を復号できない場合、受信側は以下を しなければならない:
- そのフレームを破棄する。
DECRYPTION_FAILEDエラー通知を送信する。- 連続復号失敗回数をカウントする。
- 連続失敗回数が閾値(推奨 値は 3 回)を超えた場合、CAP の鍵再交換をトリガ すべきである。
9.6.3 DAG 循環検出(4001)
DAG 循環を検出した場合:
- 受信側はその Fragment を拒否 しなければならない。
DAG_CYCLE_DETECTEDエラーを返 さなければならない。- その Fragment を DAG に追加 してはならない。
- 既存の Fragment の状態に影響を与えて はならない。
9.6.4 未知の Agreement(3001)
Fragment が未知の Agreement_ID を参照する場合:
- 受信側はその Fragment を破棄 しなければならない。
AGREEMENT_NOT_FOUNDエラーを返す。- 再ネゴシエーションをトリガ してもよい(実装定義)。
9.6.5 鍵未準備(2002)
CAP 鍵交換が未完了の状態でデータ送信を試みた場合:
- DTP_Engine は送信を拒否 しなければならない。
- 上位層の呼び出し元に
KEY_NOT_READYエラーを返 さなければならない。 - 通信チャネル内で平文形式により応答 してはならない。
9.6.6 キャッシュ満杯(6001)
未確認 Fragment キャッシュが上限に達した場合:
- 送信側は新しい Fragment の送信を一時停止 しなければならない。
- 上位アプリケーションに
BUFFER_FULL通知を送信する。 - キャッシュ領域が解放されたことを確認した後、送信を再開する。
- キャッシュ済みの Fragment を破棄 してはならない。
9.6.7 再送タイムアウト(6002)
Fragment の再送回数を使い切った場合:
- 送信側は上位アプリケーションに
RETRANSMISSION_TIMEOUTエラーを通知 しなければならない。 - セッションの一時停止または終了をトリガ すべきである。
- 無限に再送 してはならない。
9.6.8 バージョン非互換(7001)
プロトコルバージョン非互換のフレームを受信した場合(詳細は第 10 章を参照):
- 受信側はそのフレームを処理 してはならない。
VERSION_INCOMPATIBLEエラーを返 さなければならない。- エラーの
detailsフィールドに自身がサポートする最高バージョン番号を含 めなければならない。
9.6.9 権限拒否(8001、8002)
不正なロール操作の場合:
- DTP_Engine は当該操作を拒否 しなければならない。
- Observer の書き込み操作は
OBSERVER_WRITE_DENIED(8002)を返 さなければならない。 - その他の権限拒否は
PERMISSION_DENIED(8001)を返 さなければならない。
9.7 エラー復旧戦略
実装はエラータイプに応じて対応する復旧戦略を採用 しなければならない:
| エラーカテゴリ | 復旧戦略 |
|---|---|
| 1xxx フレーム処理 | フレーム破棄、ログ記録、後続フレームの受信を継続 |
| 2xxx 暗号化 | 単発失敗時はフレーム破棄、連続失敗時は鍵再ネゴシエーションをトリガ |
| 3xxx Agreement | Fragment 破棄、再ネゴシエーションをトリガする可能性 |
| 4xxx DAG | 循環:拒否、未解決:キャッシュして待機 |
| 5xxx セッション | セッション復旧を試みる、失敗時はクローズ |
| 6xxx 再開 | 送信を一時停止し、対端の応答または上位層の介入を待つ |
| 7xxx バージョン | バージョン通知を送信し、ダウングレード処理を試みる |
| 8xxx 権限 | 操作を拒否し、自動再試行 してはならない |
実装は権限エラー(8xxx)が発生した際に、同一の操作を自動的に再試行 してはならない。
