エラー

この章では、Google API のエラーモデルの概要について説明し、エラーを適切に生成して処理する方法についての一般的なガイダンスをデベロッパーに提供します。

Google API ではプロトコルに依存しない単純なエラーモデルが使用されており、さまざまな API、gRPC や HTTP などの API プロトコル、エラー コンテキスト(インスタンス、非同期、バッチ、ワークフロー エラーなど)にわたって整合性のあるエクスペリエンスを公開できます。

エラーモデル

エラーモデルは google.rpc.Status によって論理的に定義され、API エラーが発生するとそのインスタンスがクライアントに返されます。次のコード スニペットは、エラーモデルの全体的な設計を示しています。

package google.rpc;

    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 delay 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 ペイロードの例を次に示します。

  • RetryInfo は、失敗したリクエストをクライアントがいつ再試行できるかを示します。Code.UNAVAILABLE または Code.ABORTED で返される場合があります。
  • QuotaFailure は、割り当てチェックがどのように失敗したかを示します。Code.RESOURCE_EXHAUSTED で返される場合があります。
  • BadRequest は、クライアント リクエストの違反を示します。Code.INVALID_ARGUMENT で返される場合があります。

HTTP マッピング

proto3 メッセージにはネイティブ JSON エンコードがありますが、Google の API プラットフォームでは、下位互換性を維持するため、Google JSON REST API に別のエラースキーマを使用しています。

スキーマ:

// The error schema for Google REST APIs. NOTE: this schema is not used for
    // other wire protocols.
    message Error {
      // This message has the same semantics as `google.rpc.Status`. It has an extra
      // field `status` for backward compatibility with Google API Client Library.
      message Status {
        // This corresponds to `google.rpc.Status.code`.
        int32 code = 1;
        // This corresponds to `google.rpc.Status.message`.
        string message = 2;
        // 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. It also makes the error
      // more readable to developers.
      Status error = 1;
    }
    

例:

{
      "error": {
        "code": 401,
        "message": "Request had invalid credentials.",
        "status": "UNAUTHENTICATED",
        "details": [{
          "@type": "type.googleapis.com/google.rpc.RetryInfo",
          ...
        }]
      }
    }
    

RPC マッピング

異なる RPC プロトコルは、エラーモデルを異なる方法でマッピングします。gRPC の場合、エラーモデルは、生成されたコードとサポートされている各言語のランタイム ライブラリによってネイティブにサポートされます。詳細については、gRPC の API ドキュメント(たとえば、gRPC Java の io.grpc.Status)をご覧ください。

クライアント ライブラリ マッピング

Google クライアント ライブラリは、確立されたイディオムとの整合性を保つために、言語ごとに異なるエラーを表示することがあります。たとえば、google-cloud-go ライブラリでは google.rpc.Status と同じインターフェースを実装するエラーが返されますが、google-cloud-java では例外が発生します。

エラーのローカライズ

google.rpc.Statusmessage のフィールドはデベロッパー向けであり、英語でなければなりません

ユーザー向けのエラーメッセージが必要な場合は、google.rpc.LocalizedMessage を詳細フィールドとして使用します。google.rpc.LocalizedMessage のメッセージ フィールドはローカライズできますが、google.rpc.Status のメッセージ フィールドが英語になっていることを確認してください。

デフォルトでは、API サービスは認証されたユーザーのロケールまたは HTTP Accept-Language ヘッダーを使用して、ローカライズの言語を決定します。

エラーの処理

次の表に、google.rpc.Code に定義されているすべての gRPC エラーコードと、その原因の簡単な説明を示します。エラーを処理するには、返されたステータス コードの説明を確認し、それに応じて呼び出しを変更します。

HTTP RPC 説明
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 メソッドはサーバーによって実装されていません。
503 UNAVAILABLE サービス利用不可。通常、サーバーがダウンしています。
504 DEADLINE_EXCEEDED リクエスト期限を超えました。これは、呼び出し元が、メソッドのデフォルト期限よりも短い期限を設定し(つまり、要求された期限はサーバーがリクエストを処理するのに十分ではない)、リクエストがその期限内に完了しなかった場合にのみ発生します。

エラー再試行

クライアントは、503 UNAVAILABLE エラーに対して、指数バックオフを使用して再試行することができます。最小遅延は、別途ドキュメント化されていない限り、1 秒にします。

429 RESOURCE_EXHAUSTED エラーの場合、クライアントは最小 30 秒の遅延で再試行できます。このような再試行は、長時間実行するバックグラウンド ジョブに対してのみ有効です。

他のすべてのエラーについては、再試行は適用されない可能性があります。まず、リクエストがべき等であることを確認し、エラー メッセージでガイダンスを確認してください。

エラーの伝播

API サービスが他のサービスに依存している場合は、これらのサービスからエラーをそのままクライアントに伝播しないでください。エラーを変換するときには、次のことをおすすめします。

  • 実装の詳細と機密情報を非表示にします。
  • エラーに関与する当事者を調整します。たとえば、別のサービスから INVALID_ARGUMENT エラーを受け取ったサーバーが、呼び出し元に INTERNAL を伝播するようにします。

エラーの生成

サーバー デベロッパーは、クライアント デベロッパーが問題を理解して対処するための十分な情報を含むエラーを生成するようにします。同時に、エラーは多くの場合、ログに記録され、他のユーザーがアクセスできるため、ユーザーデータのセキュリティとプライバシーを考慮して、エラー メッセージとエラーの詳細で機密情報が開示されないようにする必要があります。たとえば、「クライアント IP アドレスがホワイトリスト 128.0.0.0/8 にない」というエラー メッセージは、ユーザーがアクセスできないサーバー側のポリシーに関する情報を明らかにしています。

適切なエラーを生成するには、エラー状態ごとに最適なエラーコードを選択するため、まず google.rpc.Code を十分に理解する必要があります。サーバー アプリケーションは、複数のエラー状態を並行してチェックし、最初のエラー状態を返す場合があります。

次の表に、各エラーコードと適切なエラー メッセージの例を示します。

HTTP RPC エラー メッセージの例
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 パッケージは、一連の標準エラー ペイロードを定義します。これは、カスタムエラー ペイロードよりも優先されます。次の表は、各エラーコードと一致する標準エラー ペイロードを示しています(該当する場合)。

HTTP RPC 推奨されるエラー詳細
400 INVALID_ARGUMENT google.rpc.BadRequest
400 FAILED_PRECONDITION google.rpc.PreconditionFailure
400 OUT_OF_RANGE google.rpc.BadRequest
401 UNAUTHENTICATED
403 PERMISSION_DENIED
404 NOT_FOUND google.rpc.ResourceInfo
409 ABORTED
409 ALREADY_EXISTS google.rpc.ResourceInfo
429 RESOURCE_EXHAUSTED google.rpc.QuotaFailure
499 CANCELLED
500 DATA_LOSS
500 UNKNOWN
500 INTERNAL
501 NOT_IMPLEMENTED
503 UNAVAILABLE
504 DEADLINE_EXCEEDED