要素独立の部分成功を約束する一括処理は入口の一括検証・一括デコードで壊れる — 検証は要素単位へ、テストは実経路で
MCP
テスト
設計判断
知識
判断
運用
一括入力(配列)を受けて「不正な要素だけ failed にし、正常分は処理する」契約を作っても、要素ループより手前に全体一括の検証・デコードが挟まっていると、1要素の不正が呼び出し全体をエラーにして契約が静かに死ぬ。実装は要素独立でも、入口が要素独立でなければ意味がない。
典型的な現れ方
- ツールサーバー(MCP 等)のディスパッチ層検証: フレームワークが登録スキーマで引数全体を検証してからハンドラを呼ぶ構成では、要素スキーマを厳密にすると混在入力(正常1件+不正1件)がハンドラ到達前に全体拒否される。対処は、クライアント公開用の詳細スキーマは広告として残しつつ、実行時のトップレベル検証を「配列であること+最小件数」程度に緩め、要素検証をハンドラ内の per-item 処理へ委譲する。
- 型付き構造体配列への一括デシリアライズ: 日時など型変換を伴うフィールドが1件不正なだけで、配列全体のパースが失敗し要素ループに到達しない。エンベロープは生の要素(raw message)の配列として受け、要素ごとに遅延デコードして失敗を当該要素の failed 結果へ変換する。
検知方法
この壊れ方はハンドラ関数を直接呼ぶユニットテストでは検出できない(検証層を素通りするため)。混在入力を実経路(ディスパッチ層・エンドポイント経由)で流し、「不正のみ failed・正常分は処理される・元インデックスが保持される・全体エラーにならない」を assert するテストを契約の oracle に置く。実際に、ハンドラ直呼びテストが全緑のままこの契約違反が実装に残り、実経路を読んだレビューで初めて検出された。
適用条件
全件 all-or-nothing が要件の一括処理には適用しない(その場合は入口の全体検証で早期拒否するのが正しい)。部分成功を約束する場合だけ、検証・デコードの置き場所を要素単位へ倒す。