この章では、Google API のエラーモデルの概要について説明します。また、エラーを適切に生成して処理する方法についての一般的なガイダンスもデベロッパーに提供します。
Google APIs では、プロトコルに依存しない単純なエラーモデルが使用されており、さまざまな API、各種の API プロトコル(gRPC や HTTP など)、異なるエラー コンテキスト(非同期、バッチ、ワークフロー エラーなど)にわたって一貫したエクスペリエンスを提供できます。
エラーモデル
Google APIs のエラーモデルは、google.rpc.Status
によって論理的に定義され、API エラーが発生すると、そのインスタンスがクライアントに返されます。次のコード スニペットは、エラーモデルの全体的な設計を示しています。
package google.rpc;
// The `Status` type defines a logical error model that is suitable for
// different programming environments, including REST APIs and RPC APIs.
message Status {
// A simple error code that can be easily handled by the client. The
// actual error code is defined by `google.rpc.Code`.
int32 code = 1;
// A developer-facing human-readable error message in English. It should
// both explain the error and offer an actionable resolution to it.
string message = 2;
// Additional error information that the client code can use to handle
// the error, such as retry info or a help link.
repeated google.protobuf.Any details = 3;
}
ほとんどの Google API ではリソース指向の API 設計が採用されているため、エラー処理は、多数のリソースで一連の少数の標準エラーを使用することによって、同じ設計原則に従います。たとえば、さまざまな種類の「not found」エラーを定義する代わりに、サーバーは 1 つの標準 google.rpc.Code.NOT_FOUND
エラーコードを使用して、特定のリソースが見つからないことをクライアントに伝えます。エラー空間が小さければ小さいほど、ドキュメントが単純化され、クライアント ライブラリの独特なマッピングが改善され、クライアント ロジックが単純化される一方で、実用価値のある情報の組み込みが制限されません。
エラーコード
Google API では、google.rpc.Code
によって定義された正規のエラーコードを使用しなければなりません。デベロッパーが多数のエラーコードを処理するロジックを作成する可能性は非常に低いため、個々の API で追加のエラーコードを定義しないようにする必要があります。参考として、API 呼び出すごとに平均 3 つのエラーコードを処理する場合、ほとんどのアプリケーション ロジックがエラー処理専用になり、デベロッパー エクスペリエンスが低下します。
エラー メッセージ
エラー メッセージは、ユーザーによる API エラーの理解と解決を簡単かつ迅速にするために役立つようにします。一般的に、エラー メッセージを作成する際は次のガイドラインを考慮してください。
- ユーザーが API のエキスパート ユーザーであると想定しないでください。ユーザーはクライアント デベロッパー、オペレーション担当者、IT スタッフ、アプリのエンドユーザーである場合があります。
- ユーザーがサービスの実装について何でも知っている、またはエラーのコンテキスト(ログ分析など)を熟知していると想定しないでください。
- 可能な場合は、エラー メッセージはテクニカル ユーザー(必ずしも API のデベロッパーではない)がエラーに対応して修正できるように作成してください。
- エラー メッセージは簡潔にします。必要に応じて、ユーザーが困った場合に質問したり、フィードバックを送信したり、エラー メッセージに必ずしも含まれない情報にアクセスすることができるリンクを提供してください。それ以外の場合は、詳細フィールドを使用して拡張します。
エラーの詳細
Google API では、エラーの詳細に関する標準エラー ペイロードのセットを定義しています。これは google/rpc/error_details.proto にあります。 これらは、割り当ての失敗や無効なパラメータなど、API エラーの最も一般的なニーズに対応しています。エラーコードと同様、デベロッパーは可能な限りこうした標準ペイロードを使用してください。
追加のエラー詳細タイプは、アプリケーション コードによるエラー処理を支援できる場合にのみ導入してください。人間のみが処理できるエラー情報の場合は、追加のエラー詳細タイプを導入するのではなく、エラー メッセージの内容として情報を提供し、デベロッパーが手動で処理するようにします。
error_details
ペイロードの例を次に示します。
ErrorInfo
: 安定した、拡張可能な構造化エラー情報を提供します。RetryInfo
: 失敗したリクエストをクライアントがいつ再試行できるかを示します。Code.UNAVAILABLE
またはCode.ABORTED
で返される場合があります。QuotaFailure
: 割り当てチェックがどのように失敗したかを示します。Code.RESOURCE_EXHAUSTED
で返される場合があります。BadRequest
: クライアント リクエストの違反を示します。Code.INVALID_ARGUMENT
で返される場合があります。
ErrorInfo
ErrorInfo
は、特別な種類のエラー ペイロードです。人間とアプリケーションの両方が利用できる、安定かつ拡張可能なエラー情報を提供します。それぞれの ErrorInfo
には、エラーのドメイン、エラーの理由、一連のエラーのメタデータ(この例など)の、3 つの情報が含まれます。詳細については、ErrorInfo
の定義をご覧ください。
Google API の場合、エラーのプライマリ ドメインは googleapis.com
で、対応するエラーの理由は google.api.ErrorReason
enum で定義されます。詳細については、google.api.ErrorReason
の定義をご覧ください。
エラーのローカライズ
google.rpc.Status
の message
のフィールドはデベロッパー向けであり、英語でなければなりません。
ユーザー向けのエラーメッセージが必要な場合は、google.rpc.LocalizedMessage
を詳細フィールドとして使用します。google.rpc.LocalizedMessage
のメッセージ フィールドはローカライズできますが、google.rpc.Status
のメッセージ フィールドが英語になっていることを確認してください。
デフォルトでは、API サービスは認証されたユーザーのロケールか、HTTP Accept-Language
ヘッダーまたはリクエスト内の language_code
パラメータを使用して、ローカライズの対象言語を判別します。
エラーのマッピング
Google APIs には、さまざまなプログラミング環境からアクセスできます。通常、各環境には、エラー処理の独自の方法があります。以降のセクションでは、広く使用されている環境でエラーモデルをマッピングする方法について説明します。
HTTP マッピング
proto3 メッセージには、ネイティブの JSON エンコードがありますが、Google の API プラットフォームでは、下位互換性を維持するため、Google の JSON HTTP APIs 用に別のエラースキーマを使用しています。
スキーマ:
// This message defines the error schema for Google's JSON HTTP APIs.
message Error {
// Deprecated. This message is only used by error format v1.
message ErrorProto {}
// This message has the same semantics as `google.rpc.Status`. It uses HTTP
// status code instead of gRPC status code. It has extra fields `status` and
// `errors` for backward compatibility with [Google API Client
// Libraries](https://developers.google.com/api-client-library).
message Status {
// The HTTP status code that corresponds to `google.rpc.Status.code`.
int32 code = 1;
// This corresponds to `google.rpc.Status.message`.
string message = 2;
// Deprecated. This field is only used by error format v1.
repeated ErrorProto errors = 3;
// This is the enum version for `google.rpc.Status.code`.
google.rpc.Code status = 4;
// This corresponds to `google.rpc.Status.details`.
repeated google.protobuf.Any details = 5;
}
// The actual error payload. The nested message structure is for backward
// compatibility with [Google API Client
// Libraries](https://developers.google.com/api-client-library). It also
// makes the error more readable to developers.
Status error = 1;
}
例(リンク):
{
"error": {
"code": 400,
"message": "API key not valid. Please pass a valid API key.",
"status": "INVALID_ARGUMENT",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "API_KEY_INVALID",
"domain": "googleapis.com",
"metadata": {
"service": "translate.googleapis.com"
}
}
]
}
}
gRPC マッピング
異なる RPC プロトコルは、エラーモデルを異なる方法でマッピングします。gRPC の場合、エラーモデルは、生成されたコードとサポートされている各言語のランタイム ライブラリによってネイティブにサポートされます。詳細については、gRPC の API ドキュメントをご覧ください。例については、gRPC Java の io.grpc.Status
をご覧ください。
クライアント ライブラリ マッピング
Google クライアント ライブラリは、確立されたイディオムとの整合性を保つために、言語ごとに異なるエラーを表示することがあります。たとえば、google-cloud-go ライブラリでは google.rpc.Status
と同じインターフェースを実装するエラーが返されますが、google-cloud-java では例外が発生します。
エラーの処理
次の表に、google.rpc.Code
に定義されているすべての gRPC エラーコードと、その原因の簡単な説明を示します。エラーを処理するには、返されたステータス コードの説明を確認し、それに応じて呼び出しを変更します。
HTTP | gRPC | 説明 |
---|---|---|
200 | OK |
エラーはありません。 |
400 | INVALID_ARGUMENT |
クライアントが無効な引数を指定しました。詳しくは、エラー メッセージとエラーの詳細を確認してください。 |
400 | FAILED_PRECONDITION |
空でないディレクトリの削除など、現在のシステム状態ではリクエストを実行できません。 |
400 | OUT_OF_RANGE |
クライアントが無効な範囲を指定しました。 |
401 | UNAUTHENTICATED |
OAuth トークンがない、もしくは無効、期限切れのためにリクエストが認証されませんでした。 |
403 | PERMISSION_DENIED |
クライアントに十分な権限がありません。これは、OAuth トークンに正しいスコープが割り当てられていないか、クライアントに権限が付与されていない、または API が有効になっていないことが原因で発生します。 |
404 | NOT_FOUND |
指定されたリソースが見つかりません。 |
409 | ABORTED |
同時実行の競合(読み取り - 変更 - 書き込みの競合など)。 |
409 | ALREADY_EXISTS |
クライアントが作成しようとしたリソースはすでに存在します。 |
429 | RESOURCE_EXHAUSTED |
リソース割り当てが不足しているか、レート制限に達しています。詳しくは、クライアントは google.rpc.QuotaFailure エラーの詳細を確認してください。 |
499 | CANCELLED |
リクエストはクライアントによってキャンセルされました。 |
500 | DATA_LOSS |
復元できないデータ損失またはデータ破損。クライアントはエラーをユーザーに報告する必要があります。 |
500 | UNKNOWN |
不明なサーバーエラー。通常、サーバーのバグです。 |
500 | INTERNAL |
内部サーバーエラー。通常、サーバーのバグです。 |
501 | NOT_IMPLEMENTED |
API メソッドはサーバーによって実装されていません。 |
502 | なし | サーバーに到達する前にネットワーク エラーが発生しました。通常は、ネットワークの停止や構成ミスです。 |
503 | UNAVAILABLE |
サービス利用不可。通常、サーバーがダウンしています。 |
504 | DEADLINE_EXCEEDED |
リクエスト期限を超えました。これは、呼び出し元が、メソッドのデフォルト期限よりも短い期限を設定し(つまり、要求された期限はサーバーがリクエストを処理するのに十分ではない)、リクエストがその期限内に完了しなかった場合にのみ発生します。 |
エラー時の再試行
クライアントは、503 UNAVAILABLE エラーに対して、指数バックオフを使用して再試行することができます。 最小遅延は、別途ドキュメント化されていない限り、1 秒にします。 特に記載がない限り、デフォルトの再試行は 1 回にします。
429 RESOURCE_EXHAUSTED エラーの場合、クライアントは最小 30 秒の遅延で再試行できます。このような再試行は、長時間実行するバックグラウンド ジョブに対してのみ有効です。
それ以外のすべてのエラーでは、再試行を行えない場合があります。まず、リクエストが冪等であることを確認してください。ガイダンスについては、google.rpc.RetryInfo
をご覧ください。
エラーの伝搬
API サービスが他のサービスに依存している場合は、これらのサービスからエラーをそのままクライアントに伝播しないでください。エラーを翻訳するときには、次のことをおすすめします。
- 実装の詳細と機密情報を非表示にします。
- エラーに関与する当事者を調整します。たとえば、別のサービスから
INVALID_ARGUMENT
エラーを受け取ったサーバーが、呼び出し元にINTERNAL
を伝播するようにします。
エラーの再現
ログとモニタリングを分析してエラーを解決できない場合は、シンプルかつ繰り返し実行できるテストでエラーを再現してみてください。そのテストを使用することで、トラブルシューティング用に多くの情報を収集できます。また、テクニカル サポートに問い合わせる際にそれを提供できます。
curl -v
とシステム パラメータを使用して、Google API のエラーを再現することをおすすめします。この組み合わせにより、ほぼすべての Google API リクエストを再現でき、詳細なデバッグ情報を提供できます。詳細については、呼び出す API のドキュメントをご覧ください。
エラーの生成
サーバー開発者は、クライアント開発者が問題を理解して解決するための十分な情報を含むエラーを生成するようにしてください。同時に、多くの場合、エラーは記録され、他のユーザーがアクセスできるため、ユーザーデータのセキュリティとプライバシーを考慮して、エラー メッセージとエラーの詳細で機密情報が開示されないようにする必要があります。たとえば、「Client IP address is not on allowlist 128.0.0.0/8」のようなエラー メッセージでは、サーバー側のポリシーに関する情報が公開されていますが、ログへのアクセス権を持つユーザーがアクセスできない可能性があります。
適切なエラーを生成するには、エラー状態ごとに最適なエラーコードを選択するため、まず google.rpc.Code
を十分に理解する必要があります。サーバー アプリケーションは、複数のエラー状態を並行してチェックし、最初のエラー状態を返す場合があります。
次の表に、各エラーコードと適切なエラー メッセージの例を示します。
HTTP | gRPC | エラー メッセージの例 |
---|---|---|
400 | INVALID_ARGUMENT |
リクエスト フィールド x.y.z は xxx です。[yyy、zzz] のいずれかが必要です。 |
400 | FAILED_PRECONDITION |
リソース xxx は空でないディレクトリであるため、削除することはできません。 |
400 | OUT_OF_RANGE |
パラメータ「age」は [0、125] の範囲外です。 |
401 | UNAUTHENTICATED |
無効な認証情報。 |
403 | PERMISSION_DENIED |
許可「xxx」がリソース「yyy」に対して拒否されました。 |
404 | NOT_FOUND |
リソース「xxx」が見つかりません。 |
409 | ABORTED |
リソース「xxx」のロックを取得できませんでした。 |
409 | ALREADY_EXISTS |
リソース「xxx」はすでに存在します。 |
429 | RESOURCE_EXHAUSTED |
割り当て制限「xxx」を超えました。 |
499 | CANCELLED |
リクエストはクライアントによってキャンセルされました。 |
500 | DATA_LOSS |
注を参照。 |
500 | UNKNOWN |
注を参照。 |
500 | INTERNAL |
注を参照。 |
501 | NOT_IMPLEMENTED |
メソッド「xxx」は実装されていません。 |
503 | UNAVAILABLE |
注を参照。 |
504 | DEADLINE_EXCEEDED |
注を参照。 |
エラーのペイロード
google.rpc
パッケージは、一連の標準エラー ペイロードを定義します。これは、カスタムエラー ペイロードよりも優先されます。次の表は、各エラーコードと一致する標準エラー ペイロードを示しています(該当する場合)。 高度なアプリケーションでは、エラーを処理する際、google.rpc.Status
内のエラーのペイロードを探すことをおすすめします。
HTTP | gRPC | 推奨されるエラー詳細 |
---|---|---|
400 | INVALID_ARGUMENT |
google.rpc.BadRequest |
400 | FAILED_PRECONDITION |
google.rpc.PreconditionFailure |
400 | OUT_OF_RANGE |
google.rpc.BadRequest |
401 | UNAUTHENTICATED |
google.rpc.ErrorInfo |
403 | PERMISSION_DENIED |
google.rpc.ErrorInfo |
404 | NOT_FOUND |
google.rpc.ResourceInfo |
409 | ABORTED |
google.rpc.ErrorInfo |
409 | ALREADY_EXISTS |
google.rpc.ResourceInfo |
429 | RESOURCE_EXHAUSTED |
google.rpc.QuotaFailure |
499 | CANCELLED |
|
500 | DATA_LOSS |
google.rpc.DebugInfo |
500 | UNKNOWN |
google.rpc.DebugInfo |
500 | INTERNAL |
google.rpc.DebugInfo |
501 | NOT_IMPLEMENTED |
|
503 | UNAVAILABLE |
google.rpc.DebugInfo |
504 | DEADLINE_EXCEEDED |
google.rpc.DebugInfo |