エラー

この章では、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.Statusmessage のフィールドはデベロッパー向けであり、英語でなければなりません

ユーザー向けのエラーメッセージが必要な場合は、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