プロトコル

APIエラーレスポンス設計とは?コード体系・リトライ判断・漏洩防止の実装手順

APIエラーレスポンス設計とは?コード体系・リトライ判断・漏洩防止の実装手順

APIエラーレスポンス設計とは、異常時にサーバが返すステータスコード・ヘッダー・ボディの3層を、API全体で同じ規則に揃える作業です。エンドポイントごとに場当たりで決めると、クライアント側が分岐を書き切れなくなり、障害調査でログとレスポンスが結び付かなくなります。この記事では、アプリケーションエラーコードの付番設計、クライアントが再試行を判断するために必要な情報、多言語メッセージの保持先、エラー本文からの情報漏洩を防ぐ線引き、既存APIへ後から入れる移行手順までを実装順に並べます。どこまで作り込むかの打ち切り条件も条件付きで示しました。

まとめ:エラーレスポンス設計で先に決める5点と着手順

先に決めるのは5点です。ボディの共通形式、アプリケーションエラーコードの付番規則、再試行可否をクライアントへ伝える方法、エラー本文に載せてよい情報の上限、そして相関IDの出し方。この順で固定すると、後から追加するエンドポイントが規則へ自動的に収まります。

ボディ形式は自前定義せず、RFC 9457(Problem Details for HTTP APIs・2023年7月発行)の構造を土台に置くのが基本です。標準メンバのtype・title・status・detail・instanceに、自社の拡張メンバを足す形にすれば、フレームワーク側の既製実装をそのまま使えます。逆に独自のJSON構造を先に決めてしまうと、SDK生成もログ集約も自前で書く羽目になります。

作り込みの深さは公開範囲で決めてください。社内の単一クライアント向けなら共通形式と相関IDの2点だけで足り、コード体系の整備は見送って構いません。外部公開やパートナー連携、あるいは問い合わせ窓口が別部署にあるAPIでは、エラーコードの付番と文書化まで進めないと運用が回らなくなります。境界は「エラーの意味を、実装者以外の誰かが説明する必要があるか」に置くと判断がぶれません。

エラー応答を3層に分けて設計する:ステータス・ヘッダー・ボディの役割分担

エラー応答は独立した3層で構成されます。層ごとに責務を割り当てておくと、どこへ何を書くかの議論が消えます。ステータスコードは「HTTPの語彙で何が起きたか」、ヘッダーは「クライアントが次に取る行動の指示」、ボディは「業務上の意味と、人が読む説明」です。

ボディ形式を自前定義にせず、Problem Detailsを土台に置く判断

ボディ形式の候補は、独自JSON構造とProblem Detailsの2つ。判断は後者に倒して構いません。理由は3つあります。1つ目はメディアタイプが決まっていること。応答ヘッダーのContent-Typeに application/problem+json を指定すれば、正常系のJSONと機械的に区別できます。2つ目は主要フレームワークに既製の型があること。Spring Framework 6系以降のProblemDetail、ASP.NET Core(2025年11月公開の10系を含む)のProblemDetailsクラスがそのまま使えます。3つ目が拡張メンバの扱いで、消費側は知らないメンバを無視する前提のため、後からフィールドを足しても既存クライアントが壊れません。

ここで扱うのは「土台に据えるかどうか」の判断までです。標準メンバそれぞれの定義、RFC 7807からの変更点、IANAの問題タイプURIレジストリといった規格側の詳細はRFC 9457とは?Problem Details(application/problem+json)でHTTP APIエラー応答を標準化で扱っているため、仕様の読み合わせはそちらを参照してください。

HTTPステータスとアプリケーションエラーコードを別レイヤーで持つ

設計で最初に混乱するのが、ステータスコードとアプリケーションエラーコードの関係です。両者は粒度が違うため、1対1で対応させようとすると破綻する設計です。ステータスコードは有限で、HTTPの意味論に縛られます。業務エラーは無限に増え、しかも同じ400番台に何十種類も同居します。400を返す局面そのものの判断はHTTP error 400の発生源の切り分けと直し方で扱っています。

実務では、ステータスコードを「通信・プロトコル層の結果」、拡張メンバのコードを「業務層の識別子」として二層で持ちます。たとえば在庫不足も与信限度超過も、HTTPとしてはどちらも422で表現されますが、クライアントの画面遷移は別になる。ここを分けておくと、業務エラーが増えてもステータスコードの割り当てを議論し直さずに済みます。4xxのどれを選ぶかという判断基準そのものはREST API設計のベストプラクティス|URI・冪等性・エラー応答のレビュー基準に整理があり、コード番号ごとの意味はHTTPステータスコード一覧とcurlエラーコード一覧|違い・確認方法で確認できます。

エラーコード体系の付番設計と運用:増やしすぎないための管理ルール

アプリケーションエラーコードは、一度クライアントへ公開すると事実上変更できません。分岐条件として実装へ焼き込まれるためです。付番規則と管理手順を、最初のエンドポイントを作る前に決めます。

付番規則の作り方:領域プレフィックスと固定桁の連番で衝突を防ぐ

付番は「領域プレフィックス+固定桁の連番」に落とすと管理しやすくなります。受注ならORD、在庫ならINV、認証ならAUTHのように業務領域で前置し、続けて4桁程度の連番を振る形です。ORD-0012 のような文字列であれば、ログをgrepしたときに領域単位で絞り込めます。

連番へ意味を持たせすぎないでください。「先頭1桁で重大度、次の1桁でリトライ可否」のように桁ごとに意味を詰め込む設計は、当初は整然として見えますが、分類の追加時に体系ごと破綻します。重大度や再試行可否は独立した拡張メンバとして別に持ち、コード自体は単なる識別子に留めます。判断基準は「その属性は後から変わるか」で、変わりうるものをコードへ埋め込まないという一点です。

要素 持たせる場所 変更可否
業務エラーの識別 拡張メンバのコード 不可(公開後は固定)
HTTPとしての結果 ステータスコード 不可
再試行してよいか 拡張メンバ・ヘッダー 可
利用者向けの文言 title・detail 可
個別発生の識別 instance・相関ID 都度生成

コードの追加と廃番を運用に乗せる手順と、粒度を決める2つの基準

コードは増える前提で運用します。最初から全業務エラーを網羅しようとすると、設計工程が止まります。共通形式と主要な数種だけを定義して走り出し、問い合わせが実際に発生したエラーからコードを切っていく進め方が現実的です。

粒度の基準は2つ。1つ目は「クライアントが分岐するか」で、画面表示もリトライ挙動も同じになるエラーへ別コードを振る意味はありません。2つ目は「問い合わせ対応で区別したいか」です。サポート窓口が原因を切り分けるためにコードを見るなら、そこは分ける価値があります。廃番するときはコードを削除せず、非推奨として文書へ残し、一定期間は同じコードを返し続けます。番号の再利用は事故のもとになるため禁止してください。

クライアントのリトライ判断に必要な情報をレスポンスへ載せる方法

エラー応答の価値は、受け取った側が次の行動を決められるかで決まるものです。とりわけ再試行の判断材料が抜けていると、クライアントは全エラーを一律リトライするか、一切リトライしないかの二択になります。どちらも障害時の挙動を悪化させます。

再試行の可否を拡張メンバで明示し、Retry-Afterと役割を分ける

再試行可否は、サーバ側が判断してレスポンスへ明示します。クライアントにステータスコードから推測させる設計は避けてください。500番台なら再試行してよいとは限らず、リクエスト内容に起因する恒久的な失敗が500で返っている実装は珍しくありません。

実装としては、Problem Detailsの拡張メンバに真偽値のフラグを1つ足すのが手軽です。そのうえで、待つべき秒数はヘッダーのRetry-Afterで返します。RFC 9110(HTTP Semantics・2022年6月発行)が定義するヘッダーで、秒数またはHTTP日付を取り、429と503では特に有効。役割分担は「再試行してよいかはボディ、いつ再試行するかはヘッダー」と覚えると迷いません。指数バックオフやジッタといったクライアント側の再試行アルゴリズムはリトライパターンとは?指数バックオフ・ジッター・リトライ予算の実装判断の領分で、サーバ側はその判断材料を渡すところまでを担当します。

レート制限の残量通知:標準化途上のRateLimitヘッダの扱い方

429を返すAPIでは、残量の通知方式も決めます。IETFのhttpapiワーキンググループで議論されているRateLimitヘッダ群は、2026年5月時点でdraft-ietf-httpapi-ratelimit-headersの-11が公開されている段階で、RFCとしては未発行です。仕様が固まる前に全面採用すると、確定時の書き換えが発生します。

現時点の選択肢は2つ。ドラフト準拠のヘッダー名を採用して将来の改称を受け入れるか、X-プレフィックス付きの独自ヘッダーで運用して安定を取るか。外部公開APIなら前者を、社内向けなら後者を推します。前者は他社APIと同じ名前で読めるという利点があり、後者は仕様変動の影響を受けません。いずれにせよ、上限値・残量・リセット時刻の3点を返すという中身は共通です。制限アルゴリズムの選び方と429の設計はレートリミットとは?アルゴリズム5方式と429設計・分散環境の実装で扱っています。

二重実行を防ぐ冪等キーと、409や422を返す条件の組み合わせ方

再試行を許すなら、二重実行の防止とセットで設計します。タイムアウトで応答を受け取れなかったクライアントは、処理が完了したのか失敗したのかを区別できません。POSTのような非冪等な操作では、クライアント生成の一意キーをヘッダーで受け取り、サーバ側で既処理を検出する構成にします。

ここでエラー応答の設計が絡みます。同じキーで処理中のリクエストが到着したら409、キーは同じなのにリクエストボディが違うなら422というように、状況ごとに返すものを固定してください。曖昧にすると、クライアントが「もう一度送るべきか」を判断できません。キーの発行・保存・再生の実装手順は冪等キーとは?Idempotency-Keyの発行・保存・再生の実装と二重課金の止め方にまとめています。

多言語メッセージをサーバとクライアントのどちらで持つかの判断基準

エラー文言の多言語化は、後から入れると全エンドポイントの改修になります。設計段階で保持先を決めておく項目です。

サーバが文言を返す構成とクライアントが辞書を持つ構成の使い分け

2つの構成があります。サーバがContent-Languageヘッダーと翻訳済みのtitle・detailを返す構成と、サーバはコードだけを返してクライアント側の辞書で文言を引く構成です。

外部公開APIは前者を選びます。利用者側の実装が何であるかを制御できないため、説明文まで含めて返さないと使い勝手が落ちるからです。リクエストのAccept-Languageを見て応答言語を切り替え、返した言語をContent-Languageで明示する形になります。自社のWebアプリやモバイルアプリだけがクライアントの場合は後者が適切です。画面ごとに文言の言い回しを変えたい要求が必ず出てくるためで、サーバが文言を握るとUI調整のたびにAPIのリリースが必要になります。

混在させる場合は「detailは開発者向けの英語固定、利用者向け文言はコードから引く」と役割を分けます。同じ文字列を両側で二重管理すると、翻訳漏れの温床になります。どちらの構成でも、クライアントがdetailの文字列をパースして分岐する実装は禁止と明記してください。文言変更で壊れます。

情報漏洩を防ぐエラー本文の線引きと相関IDによるログの突き合わせ

RFC 9457のセキュリティ考慮事項でも、実装の詳細やスタックダンプ、サーバ内部の情報をHTTPインターフェース経由で公開しないよう注意が促されています。エラー本文の情報量は、調査効率とのトレードオフになります。

detailに書いてよい情報と、ログにだけ残す情報の切り分け方

判断は単純な基準で足ります。「呼び出し側が自分で直せる情報だけを返す」です。必須項目の欠落、値の形式違反、権限不足といった、クライアント側の修正で解決する内容は返します。データベースの例外メッセージ、SQL文、内部のホスト名やファイルパス、フレームワークのスタックトレース、内部の主キー値は返しません。

特に事故が多いのが、開発環境向けの詳細出力を本番へ持ち込むパターンです。デバッグ用の詳細をレスポンスへ含める設定は環境変数で切り替えるのではなく、本番ビルドではコードごと通らない構成にしておくと安全側に倒れます。認証エラーでは、「ユーザーが存在しない」と「パスワードが違う」を区別して返さないでください。存在するアカウントの列挙に使われます。認証方式そのものの選び方はAPI認証の設計|方式選定マトリクスとトークン寿命・監査ログの決め方に分けてあります。

相関IDをレスポンスとログの両方へ出して障害調査を短縮する運用

返す情報を絞ると、今度は調査ができなくなります。これを埋めるのが相関ID(トレースID)です。リクエスト単位で一意の識別子を発行し、Problem Detailsのinstanceか拡張メンバとしてレスポンスへ載せ、同じ値をサーバ側のログにも出力します。

問い合わせを受けたとき、利用者から相関IDを1つ受け取ればログを直接引けます。エラー本文に内部情報を書かずに済むうえ、調査の初動が短くなる。分散トレーシングを入れているならトレースIDを流用すれば、サービスをまたいだ経路もそのまま追えます。運用としては、相関IDを画面のエラー表示にも出しておくと、利用者がスクリーンショットを送るだけで特定できる状態になります。

バリデーションエラーの構造を固定し、機械可読な検証結果を返す設計

入力検証エラーは、単一のエラーで表現できない唯一の類型です。複数フィールドが同時に不正になるため、配列で返す構造を最初に固定します。

フィールド単位のエラー配列とJSON Schemaによる形の機械検証

Problem Detailsの拡張メンバとして、フィールド名と理由の組を持つ配列を1つ定義します。要素の構造は、対象を指すポインタと、機械可読な理由コード、そして人が読む説明の3点に固定してください。ポインタはフィールド名の文字列でも動きますが、ネストした構造や配列要素を指す場面が出るため、JSON Pointer形式を採用しておくと後で困りません。

ここでの落とし穴は、エンドポイントごとに配列のキー名が揺れることです。errorsとviolationsとinvalidFieldsが同一API内に混在すると、クライアントは分岐を書き切れません。応答スキーマ自体をJSON Schemaで定義し、CIで検証まで回すと、揺れが混入した時点で気付けます。スキーマの書き方とDraft 2020-12での記述はJSON Schemaとは?JSONの構造を検証する書き方とDraft 2020-12の実装で扱っています。

なお、種類の異なるエラーが同時に起きた場合、RFC 9457は最も重要なものを1つ選んで返す方針を示しています。バリデーションのように同一種類が複数並ぶケースだけを配列で扱い、認証エラーと在庫エラーを1つのレスポンスへ同居させる設計は避けてください。HTTPの意味論から外れます。

エラー設計をどこまで作り込むか:採用条件と見送ってよい場面の判断

ここまでの内容を全部入れると、小規模なAPIでは設計が重くなります。作り込みの線引きを条件で示します。

コード体系まで作り込むべきAPIの条件:公開範囲と運用体制で決める

アプリケーションエラーコードの付番と文書化まで進めるのは、次のいずれかに当てはまる場合です。第三者へ公開するAPIであること。クライアントの実装チームがサーバ側と別組織であること。エラー内容が問い合わせ窓口や運用担当の判断材料になること。課金・決済・在庫のように、失敗の扱いを間違えると業務影響が金額で出ること。

この4条件のどれかを満たすなら、コード体系・再試行可否の明示・相関ID・多言語方針の4点が必要です。設計に数日かかりますが、運用開始後の問い合わせ対応と障害調査で回収できます。外部連携を含むAPIの設計や既存システムのAPI化については、API開発・システム連携で個別の要件に沿った進め方を相談いただけます。

共通形式だけで止めてよい場面と、後から拡張できる余地の残し方

社内の単一クライアントしか呼ばないAPI、検証目的の短命なAPI、管理画面専用のエンドポイント。これらはボディの共通形式と相関IDの2点だけで運用できます。コード体系を先に作っても、分岐に使われないまま管理コストだけが残ります。

ただし、拡張の余地は残してください。具体的には、ボディをProblem Detailsの構造にしておくこと、拡張メンバを足せる形にしておくこと、相関IDを最初から出しておくことの3点です。この3つを守っていれば、後からコード体系を導入してもレスポンス構造の作り直しになりません。逆に、エラーを文字列1つで返す実装から始めると、拡張時に全クライアントの改修が必要になります。

既存APIへ後から入れる移行手順と、旧形式との併存期間の決め方

稼働中のAPIへ入れる場合、全エンドポイントの一括切り替えは避けます。手順は、新規エンドポイントから新形式を適用し、次に問い合わせの多いエンドポイントを移し、残りを版管理の切り替え時にまとめる、という順です。

併存期間中の分岐は、Acceptヘッダーで判定する方式とAPIバージョンで分ける方式があります。既存クライアントの改修余地がないならバージョン分割を選んでください。Acceptによる分岐は、クライアントが送るヘッダーの実態を把握できている場合に限って有効です。切り替え期限は、告知から最低3か月を目安に置き、旧形式へのアクセスをログで計測しながら判断するのが妥当です。アクセスが0になる前に打ち切ると、静かに壊れるクライアントが出ます。API全体の設計工程と版管理の考え方はAPI設計とは?リソース定義からURI・スキーマ・エラー・版管理までの実装手順に整理しています。

よくある質問

エラーレスポンスでもHTTPステータスは200のままでよいですか?

避けてください。200で返すと、プロキシやCDN、監視ツール、クライアントのHTTPライブラリではすべて成功扱いです。エラー率の計測もできなくなります。GraphQLのように仕様上200を返す方式は例外ですが、REST APIでは異常時のステータスコードを正しく返し、詳細をボディで補う構成にします。

Problem Detailsのtypeには何を指定すればよいですか?

問題の種類を識別するURI参照を指定します。未指定の場合は about:blank として扱われる規定です。自社ドキュメントのURLを指定すると、受け取った開発者がそのまま説明を読めます。解決可能なURLを用意できない場合でも、絶対URIの形にしておくと将来ドキュメントを紐付けられます。詳細な規定は規格解説の記事を参照してください。

エラーコードは数値と文字列のどちらがよいですか?

文字列が適切です。ORD-0012 のように領域が読み取れる形式なら、ログを見た人がどの機能のエラーかを即座に判断できます。数値のみの体系は、桁数の管理と意味の記憶がセットで必要になり、コードが増えるほど扱いにくくなります。既存システムが数値コードで運用されている場合は、その体系へ合わせて構いません。

detailに入れる文言は誰向けに書けばよいですか?

APIを呼び出す開発者向けに書きます。エンドユーザーへそのまま表示される前提で書くと、UIの文脈に合わない文言になります。エンドユーザー向けの表示は、エラーコードを見たクライアント側が自前の文言を出す構成にしてください。外部公開APIで説明文が必要な場合のみ、翻訳済みの文言を返す方式へ寄せます。

エラー応答の設計はいつ決めればよいですか?

最初のエンドポイントを実装する前です。エラー形式は公開後の変更がクライアント改修を強制するため、URIの命名規則と同じタイミングで固定します。コード体系の中身は走りながら増やせますが、ボディの構造と相関IDの出し方だけは着手時に決め切ってください。

関連記事

お気に入りに入れた記事の一覧

この記事は以下の記事からリンクされています

資料請求

今日のトレンド記事 直近 24 時間で、いつもより多く読まれている記事

  1. 2026.10.15 テックブログ リゾートトラスト不正アクセス:会員2.6万件・カハラ横浜3.6万件の対象確認と窓口
  2. 2026.10.16 テックブログ バーガーキング不正アクセスで約1,118万件の情報漏洩|対象確認・案内メールの真偽と運営側のログ点検
  3. 2026.10.16 テックブログ ソースネクスト不正アクセスで最大2,252万件流出|ログインできない理由・パスワード再設定と会員APIの点検
  4. 2026.10.15 テックブログ 銀のさら不正アクセス:最大650万件の対象確認と窓口、パスワード変更の手順
  5. 2026.10.16 テックブログ ワラウ不正アクセスで連携トークン流出|Yahoo! JAPAN ID再連携と対象確認

RELATED POSTS 関連記事

目次