プロトコル

gRPCのステータスコードとは?16種の意味・HTTP対応表・リトライ可否を解説

gRPCのステータスコードとは?16種の意味・HTTP対応表・リトライ可否を解説

gRPCの呼び出しが落ちたとき、手元に残るのは数値ひとつと短い文字列だけです。HTTPのつもりで404や500を眺める感覚のまま向き合うと、ログにはUNKNOWNとINTERNALばかりが並ぶ。原因はコードの数が足りないことではなく、16種のエラーコードをどう割り当て、受け取った側がどう分岐するかを決めていない点にあります。扱う範囲は、16種の意味、HTTPとの対応、再試行してよい範囲、詳細の返し方、返すコードの絞り込みまで。プロトコルの基礎はgRPCの仕組みとRESTとの違いに譲ります。

まとめ|先に決める3項目とコードを選ぶときの起点

着手前に決めるのは3つです。サーバーが返してよいコードをどこまで絞るか。再試行してよいコードをどれにするか。コードだけでは足りない理由をどの型で運ぶか。ここを決めずに実装へ入ると、サーバーは例外をそのまま流してUNKNOWNを量産し、クライアントは一律リトライを掛けて障害を長引かせます。

選び分けの起点は「呼び出し側が次に何をすればよいか」に置くと迷いません。入力を直せば通るならINVALID_ARGUMENT、待って再送すれば通るならUNAVAILABLE、何をしても通らないならPERMISSION_DENIED。この基準に統一すると対応表もリトライ設定も一本の筋で決まります。

gRPCのステータスコードとは|grpc-statusで返る17個の終了コード

ステータスコードの内訳|OKを含む17個で呼び出しの終了状態を表す

gRPC公式のStatus codesは、0番のOKから16番のUNAUTHENTICATEDまで連番でコードを定義しています。合計17個のうち成功を表すのはOKひとつで、残る16個がエラーコードです。「16種」と呼ばれるのはこの16個で、OKを数に入れるかどうかの違いに過ぎません。

返却の実体は、応答のトレーラに載るgrpc-statusという数値のメタデータで、人が読む短い文字列をgrpc-messageで添えられます。この2つが標準のエラーモデルにあたります。

HTTPのステータスコードとは層が違う|本体の応答は常に200

混乱の元になりやすいのが、gRPCの通信そのものはHTTP/2の上を走るという事実です。メソッドがエラーで終わってもHTTPのレスポンス自体は200で返り、失敗の事実はgrpc-statusだけが持つ。ロードバランサのログを200で埋めながらアプリケーションは失敗し続ける状態が普通に起こります。

逆にHTTP側が200以外で返るなら、gRPCのメソッドまで到達していない合図です。経路上のプロキシが拒否した、パスが存在しない、といったケースにあたる。HTTP側の番号の意味はHTTPステータスコード一覧と確認方法にまとめてあります。

誰が生成するか|ライブラリが返すコードとアプリケーションが返すコード

16種のうち一部は、アプリケーションのコードを一行も書かずに返ってきます。gRPC公式のstatuscodes.mdは、キャンセルでCANCELLED、メソッド不在でUNIMPLEMENTED、停止中や接続断でUNAVAILABLE、サーバー側の例外送出でUNKNOWN、メッセージサイズ超過でRESOURCE_EXHAUSTEDが生成されると列挙しています。

反対に、ライブラリが決して生成せずユーザーコードだけが返すコードも明記されています。3番・5番・6番・9番・10番・11番・15番の7つです。この7つがログに出ていればアプリケーションが意図して返したもので、それ以外は基盤側の事情が混ざっている可能性がある。切り分けの第一手として使える区別でしょう。

エラーコード全16種の一覧|番号・意味・想定する使いどころを整理

番号 コード 意味 受け手が取る行動
1 CANCELLED 呼び出しが取り消された 後始末して終了
2 UNKNOWN 分類できない失敗 調査対象として記録
3 INVALID_ARGUMENT 引数の値が不正 入力を直して再送
4 DEADLINE_EXCEEDED 期限内に返らなかった 期限か処理を見直す
5 NOT_FOUND 対象が存在しない 識別子を確認する
6 ALREADY_EXISTS 作る対象が既にある 既存を参照へ切替
7 PERMISSION_DENIED 実行の権限が足りない 権限付与を依頼
8 RESOURCE_EXHAUSTED 割当や容量の枯渇 間隔を空けて再送
9 FAILED_PRECONDITION 状態が前提を満たさない 状態を直すまで停止
10 ABORTED 競合などで中断した 上位の処理から再試行
11 OUT_OF_RANGE 有効範囲の外を指定 範囲を直して再送
12 UNIMPLEMENTED 未実装または非対応 再試行せず打ち切り
13 INTERNAL 不変条件が壊れた 調査対象として記録
14 UNAVAILABLE 一時的に利用できない 退避付きで再試行
15 DATA_LOSS データの喪失や破損 再試行せず打ち切り
16 UNAUTHENTICATED 認証情報が無効 資格情報を取り直す

入力と前提状態の誤り|3番・9番・11番のコードを分ける基準とは

取り違えが多いのがこの3つです。INVALID_ARGUMENTは、状態がどうであれ値そのものが受け付けられない場合に使います。日付の書式違いや必須フィールドの欠落が典型です。FAILED_PRECONDITIONは値は正しいがシステム側が受け入れられる状態にないことを指し、公式は状態が直るまで再試行してはならないと位置づけている。OUT_OF_RANGEは範囲外の指定に限った特殊形です。

存在と資源の誤り|5番・6番・8番で足りないものを言い分ける

NOT_FOUNDとALREADY_EXISTSは対です。取得や更新で対象が無ければ前者、作成で既にあれば後者。ここで判断が要るのは、権限が無くて見えていない対象をどちらで返すかという設計です。存在の有無そのものを秘匿したい業務では、あえてNOT_FOUNDに寄せる選択もあります。

RESOURCE_EXHAUSTEDは割当や空き容量の枯渇に使う。ライブラリ自身もメッセージサイズの上限超過でこのコードを生成するため、ログで見たら業務上のレート制限か既定4MiBの超過かをまず切り分けます。

認証と権限の誤り|16番と7番は本人確認と操作可否で分かれる

UNAUTHENTICATEDは「誰なのか確認できない」、PERMISSION_DENIEDは「誰かは分かるが操作が許されていない」を意味します。トークンの期限切れや署名検証の失敗は前者、権限不足は後者。混ぜて返すと、クライアントは再認証すべきか諦めるべきかを判断できません。

サーバー側と経路の異常|14番・13番・2番・15番の使い分けの目安

UNAVAILABLEは、いま落ちているが少し待てば戻る失敗です。停止中、接続断、keepaliveの発火など、ライブラリ側からも生成される。INTERNALは不変条件が壊れたことを示し、プロト解析や圧縮解除の失敗のように通信の前提が崩れた場面で返ります。

UNKNOWNは分類できなかった残余で、サーバー側の例外送出時の既定値でもあります。ここが多い実装は、例外をコードへ写す層が無いだけです。DATA_LOSSは喪失や破損という最も重い宣言で、使う場面を限定しないと単なる読み出し失敗にまで付いてしまいます。

HTTPステータスコードとの対応表|変換は向きによって意味が変わる

gRPCからHTTPへの対応|ゲートウェイ越しに公開するときの変換表

gRPCのサービスをHTTPとJSONで外へ出すなら、コードをHTTPステータスコードへ写す必要が出ます。googleapisのcode.protoには各コードに対応するHTTPの値がコメントで示され、ゲートウェイ実装の事実上の基準になっている。CANCELLEDだけは499という非標準の値で、経路によっては変換されずに落ちる点に注意が要ります。

gRPCコード HTTP gRPCコード HTTP
OK 200 ABORTED 409
CANCELLED 499 OUT_OF_RANGE 400
UNKNOWN 500 UNIMPLEMENTED 501
INVALID_ARGUMENT 400 INTERNAL 500
DEADLINE_EXCEEDED 504 UNAVAILABLE 503
NOT_FOUND 404 DATA_LOSS 500
ALREADY_EXISTS 409 UNAUTHENTICATED 401
PERMISSION_DENIED 403 RESOURCE_EXHAUSTED 429
FAILED_PRECONDITION 400 – –

HTTPからgRPCへの対応|grpc-statusが無い応答を受け取ったとき

逆向きの変換は別のルールで、用途も違います。grpc/grpcリポジトリのhttp-grpc-status-mapping.mdは、grpc-statusを含まない応答を受けたクライアントが使う表として、400をINTERNAL、401をUNAUTHENTICATED、403をPERMISSION_DENIED、404をUNIMPLEMENTED、429と502と503と504をUNAVAILABLE、それ以外をUNKNOWNに写すと定めます。

同ドキュメントには、この表をサーバーがHTTPコードを決める用途に使ってはならないという但し書きが付く。前段で失敗した以上、業務的な意味づけはできないという判断です。運用への影響は小さくありません。UNIMPLEMENTEDの急増が、メソッド未実装なのかプロキシの404なのかで対処はまるで違う。gRPC-Webのプロキシ構成のように途中で1枚変換が入る経路では、切り分けの手順を先に決めておくと迷いません。

対応表で迷いやすい組|400に3つ・409に2つ・500に3つが集まる

HTTP側から見ると、複数のgRPCコードが同じ番号へ潰れます。400には3番・9番・11番、409には6番と10番、500には2番・13番・15番が集まる。HTTPへ落とした時点でこの違いは失われるため、gRPCのコードを保ったまま計測する層を持つか、変換時に元のコードをログへ残すかを設計に含めておくべきです。

リトライ可否の判断|再試行してよいコードと待っても直らないコード

再試行を許すのは実質2つ|14番のUNAVAILABLEと10番のABORTED

gRPC公式のStatus codesは、再試行の扱いを3つに書き分けています。失敗した呼び出しだけを再試行できるならUNAVAILABLE。上位の階層からやり直す必要があるならABORTED。状態が明示的に直るまで再試行してはならないものがFAILED_PRECONDITIONです。

この3分類が自動再試行の対象範囲を決めます。ライブラリに任せてよいのはUNAVAILABLEだけで、ABORTEDは上位のロジックに任せます。

コード 自動再試行 方針
UNAVAILABLE 入れてよい 指数退避とジッタで再送
ABORTED 入れない 上位の処理単位でやり直す
RESOURCE_EXHAUSTED 条件付き 長い間隔と上限を設ける
DEADLINE_EXCEEDED 入れない 期限そのものを見直す
FAILED_PRECONDITION 入れない 状態が直るまで送らない
INTERNAL・UNKNOWN 入れない 原因不明のまま増幅させない

retryPolicyの書き方|4つのフィールドと再試行の絞り込み設定

gRPCはサービス設定で再試行を宣言的に書けます。retryPolicyを構成するのはmaxAttempts、initialBackoff、maxBackoff、backoffMultiplier、対象を絞るretryableStatusCodesです。待ち時間には±20%のジッタが加わり、複数クライアントの再送が同じ瞬間に揃うことを避けられます。

{
  "methodConfig": [{
    "name": [{"service": "example.OrderService"}],
    "retryPolicy": {
      "maxAttempts": 4,
      "initialBackoff": "0.1s",
      "maxBackoff": "1s",
      "backoffMultiplier": 2,
      "retryableStatusCodes": ["UNAVAILABLE"]
    }
  }]
}

あわせて設定したいのがretryThrottlingです。maxTokensとtokenRatioでサーバー単位のトークンを増減させ、失敗が続いて半分を下回ると再試行そのものを止める。障害中のサーバーへ再送が殺到する事態をクライアント側だけで抑えられます。

DEADLINE_EXCEEDEDを再試行対象に入れてはいけない理由とは

DEADLINE_EXCEEDEDは「期限内に返らなかった」であり、「失敗した」ではありません。サーバー側は処理を続けている可能性があり、更新が完了したかをクライアントは知り得ない。自動再試行を掛けると、同じ更新が二重に走る危険が生じます。

加えて、デッドラインは呼び出し全体に対する期限です。1回目で使い切っている以上、2回目に残る時間はほとんど無く、即座に同じコードで返るだけ。対処は期限の値を見直すか、処理を分割するか、非同期の受け付け方式へ変えるかのいずれかになるでしょう。

詳細を返す設計|error detailsで機械可読な理由をクライアントへ渡す

標準モデルとリッチモデル|コードとメッセージだけでは足りない場面

標準のエラーモデルは、コードと任意の文字列メッセージだけで構成されます。gRPC公式のError handlingはこれを全言語が対応する共通の土台と位置づけている。ただし文字列は人間向けで、どのフィールドがなぜ不正なのかを機械的に読ませたい場面では足りません。そこで拡張モデルがあり、google.rpc.Statusに詳細のリストを持たせ、protobufのバイナリをトレーリングメタデータへ載せて運びます。文字列を正規表現で解析する壊れやすい実装から抜け出せます。

標準の詳細型|ErrorInfoとBadRequestとRetryInfoの使い分け

詳細として載せる型も標準セットがあります。ErrorInfoは機械が読む安定した理由コードを持ち、種別の識別に向く。BadRequestはフィールド単位の違反理由を並べ、入力検証の結果をそのまま返せます。

詳細の型 組み合わせるコード 渡す内容
ErrorInfo 広く共通 安定した理由コード
BadRequest INVALID_ARGUMENT 不正なフィールドと理由
PreconditionFailure FAILED_PRECONDITION 満たされない前提の種別
QuotaFailure RESOURCE_EXHAUSTED 超過した割当の名前
RetryInfo UNAVAILABLEなど 再試行してよい時刻
LocalizedMessage 利用者へ見せる場合 言語別の説明文

勘所は、コードは粗く保ち、細かい区別をErrorInfoの理由コードへ寄せることです。16種は業務都合で拡張できないため、固有の区別を持ち込むと意味が濁る。分岐の骨格はコード、表示や個別対応は詳細で分けます。なお詳細はトレーラに載るためスタックトレースを詰めるとヘッダ上限に当たり、公式が実装例を示すのはC++・Go・Java・Python・Rubyで言語差がある点は前提に置いてください。

クライアント実装の分岐設計|コードで分けて詳細で理由を説明する

分岐は3つに畳む|再試行する・入力を直す・その場で打ち切るの3択

16種すべてに個別の処理を書く実装は、書いた本人にしか保守できません。呼び出し側が取れる行動は、再試行する・直して送り直す・上位へ伝えるの3つだけです。この3群へ写す関数を1つ用意し、個々の呼び出しはその結果だけを見るようにします。

分岐 該当コード 実装での扱い
再試行する UNAVAILABLE 退避付きで自動再送
やり直す ABORTED 業務処理の単位で再構成
入力を直す 3番・11番・16番 利用者へ差し戻す
状態を直す FAILED_PRECONDITION 前提を整えてから再送
打ち切る 7番・12番・15番 再送せず上位へ伝える
記録する UNKNOWN・INTERNAL 調査待ちとして通知

一元化と観測|インターセプタで記録し監視の軸をコード別に置く

再試行、ログ出力、メトリクスの記録は、呼び出しごとに書くと必ずどこかで抜けます。クライアントインターセプタで一度だけ実装し全メソッドへ適用すると漏れがない。自動再試行はretryPolicyに任せられるため、インターセプタ側は記録と写像に専念させるのが素直です。ストリーミングでは終了コードが最後のメッセージを読み切った時点で確定するため、unaryと同じ書き方では途中まで受信済みのデータの扱いが宙に浮きます。方式ごとの受け取り方はgRPCストリーミングの4方式と切断対策で整理しています。

運用で最初に効くのは、メソッド名とコードの2軸でカウンタを持つことです。HTTP側の200しか見ていない監視では、この情報は最後まで得られない。UNKNOWNとINTERNALの比率は実装の健全さの指標になり、この2つが目立って増えるなら例外をコードへ写す層が抜けている疑いが濃いでしょう。

採用の境界|サーバー側で返してよいコードを許可リストで絞る判断

許可リストで運用する3条件|使うコードを先に決めて実装を縛る

16種すべてを使える状態にすると、実装者ごとに割り当てがばらつきます。返してよいコードを先に決めレビューで弾く運用にすると、クライアント側の分岐が安定する。採ってよいのは次の3条件が揃うときです。

ひとつ、サーバーとクライアントの両方を自社で設計できること。ふたつ、公開範囲が社内システム間か、契約で仕様を握れる相手に限られること。みっつ、種別の細分化をErrorInfoの理由コードで吸収できること。揃うなら、業務APIで使うコードは3番・5番・6番・7番・8番・9番・16番の7つまで絞れます。

逆に、不特定多数の外部開発者へ公開するAPIや、既存のHTTP APIと並走する移行期には向きません。相手の実装が想定外のコードを前提にしている場合があるためです。

見送る使い方|UNKNOWNの放置とINTERNALの濫用が招く運用負債

やめたほうがよい使い方も条件で言い切れます。第一に、例外をそのまま流してUNKNOWNにする運用。原因が分類されないまま蓄積し、監視でも切り分けられない。例外の種類をコードへ写すハンドラを1枚挟むだけで解消します。

第二に、迷ったらINTERNALという運用です。不変条件が壊れたという強い宣言で、本来は緊急度の高い通知に結び付けるもの。日常的な入力エラーまで含めると通知が鳴り続けます。第三に、ABORTEDやDATA_LOSSを再試行対象へ入れる設定。前者は同じ競合を繰り返すだけです。

受託開発での取り決め|APIエラー仕様を契約前に合意しておく項目

複数社でシステムを分担する案件では、エラーの取り決めが抜けたまま結合試験に入りがちです。正常系のスキーマは.protoで共有されるのに、失敗時の表現は各社の実装任せになる。片方はNOT_FOUNDを想定し、もう片方は空応答を返す食い違いが終盤で出てきます。

合意しておきたいのは4項目です。返すコードの許可リスト。理由コードの命名と管理者。再試行してよいコードと待ち時間の下限。詳細を読めないクライアントが混ざる場合の縮退動作。この4つを設計書に書けば、後から参加する実装者も同じ判断ができます。エラー仕様を含むAPI設計や既存システムとの接続については、API開発・システム連携で相談を受け付けています。

よくある質問

gRPCのステータスコードは16種と17種のどちらが正しいですか?

どちらも同じものを指しています。公式が定義するのは0番のOKから16番までの17個で、成功を表すOKを除いた16個がエラーコードです。エラーハンドリングの文脈では16種、定義の総数では17個と読み替えれば齟齬はありません。

独自のエラーコードを追加することはできますか?

コード自体を増やすことはできません。grpc-statusの値は仕様で決まっており、範囲外の値を返しても受け側が解釈できないためです。業務固有の区別が要るなら、コードは既存の16種から選び、ErrorInfoの理由コードで細分化します。

ストリーミングの途中でエラーを返すとコードはどう届きますか?

ストリームの終了時にトレーラとして届きます。それまでに送ったメッセージはすでにクライアントへ渡っており、途中まで処理が進んだ状態でコードだけが失敗を告げる。どこまで処理済みかを伝えるなら、メッセージに通し番号を持たせる設計が要ります。

DEADLINE_EXCEEDEDとUNAVAILABLEはどう見分けますか?

前者は期限切れ、後者は接続できないか一時的に応答できない状態です。処理が長引いたならDEADLINE_EXCEEDED、接続が確立しない、停止中、keepaliveが切れたならUNAVAILABLE。自動再試行してよいのは後者だけと覚えておくと判断を誤りません。

エラーの内容をログにどこまで残すべきですか?

コード、理由コード、追跡用の識別子の3点は必須と考えてよいでしょう。リクエスト本文をそのまま残す運用は個人情報が混ざるため避けます。grpc-messageにも内部構造を書かず、詳しい情報は識別子でサーバー側のログに紐づけます。

関連記事

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

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

資料請求

今日のトレンド記事 直近 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.15 テックブログ アエナ不正アクセス:最大81.7万人の対象確認と窓口、退会と不審メールの見分け方

RELATED POSTS 関連記事

目次