第 9 章 エラー処理

9.1 エラー処理モデル

DTP 実装は「検出 - 通知 - 復旧」の三段階エラー処理モデルに従わ なければならない

  1. 検出:異常状況を識別する。
  2. 通知:対端または上位層にエラー情報を送信する。
  3. 復旧:エラーの種類に応じて復旧措置を講じる。

実装はエラーを検出した際に、通知することなく黙ってフレームを破棄 してはならない

9.2 エラーコード体系

DTP は以下のエラーコード体系を使用 しなければならない。エラーコードは非負整数で なければならず、機能モジュールごとに 8 つの範囲に区分される:

範囲カテゴリ処理戦略
1xxxフレーム処理エラーフレーム破棄 + 送信側に通知
2xxx暗号化エラーフレーム破棄 + 送信側に通知 + 鍵再ネゴシエーションをトリガする可能性
3xxxAgreement エラーFragment 破棄 + 送信側に通知 + 再ネゴシエーションをトリガする可能性
4xxxDAG エラーFragment 拒否 + 送信側に通知、またはキャッシュして待機
5xxxセッションエラーセッション復旧を試みる + 失敗時にクローズして上位層に通知
6xxx再開エラー送信を一時停止 + 上位アプリケーションに通知
7xxxバージョンエラーバージョン非互換通知を送信 + ダウングレード処理を試みる
8xxx権限エラー操作を拒否 + 要求側に通知

9.3 エラーコード定義

実装は以下の規範化されたエラーコード定義を使用 しなければならない。列挙されていないエラーコードを使用 してはならない。拡張が必要な場合、本仕様の後続バージョンで定義 しなければならない

9.3.1 フレーム処理エラー(1xxx)

エラーコード名称発火条件
1001FRAME_DESERIALIZATION_FAILED受信したバイナリデータを LogicalFrame にデシリアライズできない
1002FRAME_INVALID_FORMATLogicalFrame の構造が無効、または必須フィールドが欠落している

9.3.2 暗号化エラー(2xxx)

エラーコード名称発火条件
2001DECRYPTION_FAILEDPayload の復号に失敗(誤った鍵またはデータ破損)
2002KEY_NOT_READYCAP 鍵交換が未完了であり、データ伝送を拒否する

9.3.3 Agreement エラー(3xxx)

エラーコード名称発火条件
3001AGREEMENT_NOT_FOUNDFragment が未知の Agreement_ID を参照している
3002AGREEMENT_EXPIRED参照された Agreement が有効期限切れ(validityPeriod を超過)
3003AGREEMENT_NEGOTIATION_FAILEDネゴシエーションが完了できない(タイムアウト、対端の再ネゴシエーション拒否など)

9.3.4 DAG エラー(4xxx)

エラーコード名称発火条件
4001DAG_CYCLE_DETECTEDFragment を追加すると DAG 上に循環が形成される
4002DAG_DEPENDENCY_UNRESOLVEDFragment の依存がキャッシュタイムアウト内に解決されなかった

9.3.5 セッションエラー(5xxx)

エラーコード名称発火条件
5001SESSION_NOT_FOUND参照された Session_ID が存在しない
5002SESSION_TIMEOUTセッションが非アクティブによりタイムアウト
5003SESSION_RESTORE_FAILED再接続後のセッション復元に失敗

9.3.6 再開エラー(6xxx)

エラーコード名称発火条件
6001BUFFER_FULL送信側の未確認 Fragment キャッシュが容量上限に達した
6002RETRANSMISSION_TIMEOUTFragment 再送がタイムアウトしても確認応答を受信できない(再送回数を使い切った)

9.3.7 バージョンエラー(7xxx)

エラーコード名称発火条件
7001VERSION_INCOMPATIBLE受信フレームのプロトコルバージョン番号が自身のサポートバージョンより高い

9.3.8 権限エラー(8xxx)

エラーコード名称発火条件
8001PERMISSION_DENIED現在のロールでは当該操作を実行できない
8002OBSERVER_WRITE_DENIEDObserver が書き込み操作を試みた(Observer は読み取り専用)

9.4 エラーコードの一意性

実装はエラーコードの一意性を保証 しなければならない

  1. 各エラーコードは一意のエラータイプに対応 しなければならない
  2. 異なるエラータイプが同一のエラーコードを共有 してはならない
  3. 実装は本仕様で既に割り当て済みのエラーコードを再定義 してはならない

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 をデシリアライズできない場合、受信側は以下を しなければならない

  1. そのフレームを破棄する。
  2. FRAME_DESERIALIZATION_FAILED エラー通知を送信する。
  3. デシリアライズ失敗を理由にセッションをクローズ してはならない

9.6.2 復号失敗(2001)

受信した Payload を復号できない場合、受信側は以下を しなければならない

  1. そのフレームを破棄する。
  2. DECRYPTION_FAILED エラー通知を送信する。
  3. 連続復号失敗回数をカウントする。
  4. 連続失敗回数が閾値(推奨 値は 3 回)を超えた場合、CAP の鍵再交換をトリガ すべきである

9.6.3 DAG 循環検出(4001)

DAG 循環を検出した場合:

  1. 受信側はその Fragment を拒否 しなければならない
  2. DAG_CYCLE_DETECTED エラーを返 さなければならない
  3. その Fragment を DAG に追加 してはならない
  4. 既存の Fragment の状態に影響を与えて はならない

9.6.4 未知の Agreement(3001)

Fragment が未知の Agreement_ID を参照する場合:

  1. 受信側はその Fragment を破棄 しなければならない
  2. AGREEMENT_NOT_FOUND エラーを返す。
  3. 再ネゴシエーションをトリガ してもよい(実装定義)。

9.6.5 鍵未準備(2002)

CAP 鍵交換が未完了の状態でデータ送信を試みた場合:

  1. DTP_Engine は送信を拒否 しなければならない
  2. 上位層の呼び出し元に KEY_NOT_READY エラーを返 さなければならない
  3. 通信チャネル内で平文形式により応答 してはならない

9.6.6 キャッシュ満杯(6001)

未確認 Fragment キャッシュが上限に達した場合:

  1. 送信側は新しい Fragment の送信を一時停止 しなければならない
  2. 上位アプリケーションに BUFFER_FULL 通知を送信する。
  3. キャッシュ領域が解放されたことを確認した後、送信を再開する。
  4. キャッシュ済みの Fragment を破棄 してはならない

9.6.7 再送タイムアウト(6002)

Fragment の再送回数を使い切った場合:

  1. 送信側は上位アプリケーションに RETRANSMISSION_TIMEOUT エラーを通知 しなければならない
  2. セッションの一時停止または終了をトリガ すべきである
  3. 無限に再送 してはならない

9.6.8 バージョン非互換(7001)

プロトコルバージョン非互換のフレームを受信した場合(詳細は第 10 章を参照):

  1. 受信側はそのフレームを処理 してはならない
  2. VERSION_INCOMPATIBLE エラーを返 さなければならない
  3. エラーの details フィールドに自身がサポートする最高バージョン番号を含 めなければならない

9.6.9 権限拒否(8001、8002)

不正なロール操作の場合:

  1. DTP_Engine は当該操作を拒否 しなければならない
  2. Observer の書き込み操作は OBSERVER_WRITE_DENIED(8002)を返 さなければならない
  3. その他の権限拒否は PERMISSION_DENIED(8001)を返 さなければならない

9.7 エラー復旧戦略

実装はエラータイプに応じて対応する復旧戦略を採用 しなければならない

エラーカテゴリ復旧戦略
1xxx フレーム処理フレーム破棄、ログ記録、後続フレームの受信を継続
2xxx 暗号化単発失敗時はフレーム破棄、連続失敗時は鍵再ネゴシエーションをトリガ
3xxx AgreementFragment 破棄、再ネゴシエーションをトリガする可能性
4xxx DAG循環:拒否、未解決:キャッシュして待機
5xxx セッションセッション復旧を試みる、失敗時はクローズ
6xxx 再開送信を一時停止し、対端の応答または上位層の介入を待つ
7xxx バージョンバージョン通知を送信し、ダウングレード処理を試みる
8xxx 権限操作を拒否し、自動再試行 してはならない

実装は権限エラー(8xxx)が発生した際に、同一の操作を自動的に再試行 してはならない