API エラーの処理

Google カレンダー API は、次の 2 つのレベルのエラー情報を返します。

  • ヘッダーの HTTP エラーコードとメッセージ
  • エラーの処理方法を判断するのに役立つ追加の詳細情報を含むレスポンス本文の JSON オブジェクト。

このページの残りの部分では、カレンダー エラーのリファレンスと、アプリでの処理方法に関するガイダンスを示します。

指数バックオフを実装する

Google Cloud Storage のドキュメントでは、指数バックオフと、Google API での使用方法について説明しています。

エラーと推奨されるアクション

このセクションでは、リストに記載されている各エラーの完全な JSON 表現と、エラーを処理するために推奨される操作について説明します。

400: Bad Request

ユーザーエラー。このエラーは、必須のフィールドまたはパラメータを指定しない場合、無効な値を指定する場合、または無効なフィールドの組み合わせを指定する場合に発生します。

{
  "error": {
    "errors": [
      {
        "domain": "calendar",
        "reason": "timeRangeEmpty",
        "message": "The specified time range is empty.",
        "locationType": "parameter",
        "location": "timeMax"
      }
    ],
    "code": 400,
    "message": "The specified time range is empty."
  }
}

推奨される対応: これは永続的なエラーであるため、再試行しないでください。代わりにエラー メッセージを読み、それに応じてリクエストを変更してください。

401: Invalid Credentials

無効な認証ヘッダー。使用しているアクセス トークンは、有効期限が切れているか無効です。

{
  "error": {
    "errors": [
      {
        "domain": "global",
        "reason": "authError",
        "message": "Invalid Credentials",
        "locationType": "header",
        "location": "Authorization"
      }
    ],
    "code": 401,
    "message": "Invalid Credentials"
  }
}

推奨される対応:

  • 有効期間の長い更新トークンを使用して、新しいアクセス トークンを取得します。
  • 失敗した場合は、OAuth 2.0 でリクエストを承認するの説明に沿って、OAuth フローをユーザーに案内します。
  • サービス アカウントでこのエラーが発生した場合は、サービス アカウントのページの手順をすべて完了していることを確認してください。

403: ユーザーのレート制限を超えています

Google Cloud コンソールの制限のいずれかに達した。

{
  "error": {
    "errors": [
      {
        "domain": "usageLimits",
        "reason": "userRateLimitExceeded",
        "message": "User Rate Limit Exceeded"
      }
    ],
    "code": 403,
    "message": "User Rate Limit Exceeded"
  }
}

推奨される対応:

  • アプリが割り当ての管理のベスト プラクティスに沿っていることを確認します。
  • コンソール プロジェクトでユーザーあたりの割り当てを引き上げます。
  • 1 人のユーザーが Google Workspace アカウントの多くのユーザーに代わって大量のリクエストを行っている場合は、ドメイン全体の委任でサービス アカウントを使用し、quotaUser パラメータを設定することを検討してください。
  • 指数バックオフを使用します。

403: Rate Limit Exceeded

ユーザーが Calendar API のカレンダーごとまたは認証済みユーザーごとの最大リクエスト率に達した。

{
  "error": {
    "errors": [
      {
        "domain": "usageLimits",
        "reason": "rateLimitExceeded",
        "message": "Rate Limit Exceeded"
      }
    ],
    "code": 403,
    "message": "Rate Limit Exceeded"
  }
}

推奨される対応: rateLimitExceeded エラーは 403 または 429 のエラーコードを返します。これらは機能的に類似しているため、指数バックオフを使用して同じ方法で処理する必要があります。また、アプリが割り当ての管理のベスト プラクティスに準拠していることを確認してください。

403: カレンダーの使用制限を超えている

ユーザーが、Google ユーザーとインフラストラクチャを不正行為から保護するために設けられているカレンダーの制限のいずれかに達しました。

{
  "error": {
    "errors": [
      {
        "domain": "usageLimits",
        "message": "Calendar usage limits exceeded.",
        "reason": "quotaExceeded"
      }
    ],
    "code": 403,
    "message": "Calendar usage limits exceeded."
  }
}

推奨される対応:

403: 主催者以外は禁止

イベント更新リクエストが、主催者以外のコピーで共有イベント プロパティのいずれかを設定しようとしています。共有プロパティ(guestsCanInviteOthersguestsCanModifyguestsCanSeeOtherGuests など)を設定できるのは、主催者のみです。

{
  "error": {
    "errors": [
      {
        "domain": "calendar",
        "reason": "forbiddenForNonOrganizer",
        "message": "Shared properties can only be changed by the organizer of the event."
      }
    ],
    "code": 403,
    "message": "Shared properties can only be changed by the organizer of the event."
  }
}

推奨される対応:

  • Events: insertEvents: import、または Events: update を使用していて、リクエストに共有プロパティが含まれていない場合、これは共有プロパティをデフォルト値に設定しようとしているのと同じです。代わりに Events: patch の使用をご検討ください。
  • リクエストに共有プロパティが含まれている場合は、主催者のコピーを更新する場合にのみ、これらのプロパティを変更するようにしてください。

404: 見つかりません

指定されたリソースが見つかりませんでした。この問題は、いくつかのケースで発生する可能性があります。次に例を示します。

  • リクエストされたリソース(指定された ID を持つ)が一度も存在しなかった場合。
  • ユーザーがアクセスできないカレンダーにアクセスしようとした場合。
{
  "error": {
    "errors": [
      {
        "domain": "global",
        "reason": "notFound",
        "message": "Not Found"
      }
    ],
    "code": 404,
    "message": "Not Found"
  }
}

推奨される対応: 指数バックオフを使用します。

409: リクエストされた識別子はすでに存在します

指定された ID のインスタンスはストレージにすでに存在します。

{
  "error": {
    "errors": [
      {
        "domain": "global",
        "reason": "duplicate",
        "message": "The requested identifier already exists."
      }
    ],
    "code": 409,
    "message": "The requested identifier already exists."
  }
}

推奨される対応: 新しいインスタンスを作成する場合は、新しい ID を生成します。それ以外の場合は、events.update メソッドを使用します。

409: Conflict

events.batch オペレーション内のバッチ処理されたアイテムは、リクエストされた他のバッチ処理されたアイテムとのオペレーションの競合が原因で実行できません。

{
  "error": {
    "errors": [
      {
        "domain": "global",
        "reason": "conflict",
        "message": "Conflict"
      }
    ],
    "code": 409,
    "message": "Conflict"
  }
}

推奨される対応: 完了したアイテムと失敗したアイテムを削除し、残りのアイテムを別の events.batch または対応する単一イベント オペレーションで再試行します。

410: Gone

syncToken パラメータまたは updatedMin パラメータが無効になりました。このエラーは、すでに削除されているイベントを削除しようとした場合にも発生することがあります。

{
  "error": {
    "errors": [
      {
        "domain": "calendar",
        "reason": "fullSyncRequired",
        "message": "Sync token is no longer valid, a full sync is required.",
        "locationType": "parameter",
        "location": "syncToken"
      }
    ],
    "code": 410,
    "message": "Sync token is no longer valid, a full sync is required."
  }
}

または

{
  "error": {
    "errors": [
      {
        "domain": "calendar",
        "reason": "updatedMinTooLongAgo",
        "message": "The requested minimum modification time lies too far in the past.",
        "locationType": "parameter",
        "location": "updatedMin"
      }
    ],
    "code": 410,
    "message": "The requested minimum modification time lies too far in the past."
  }
}

または

{
  "error": {
    "errors": [
      {
        "domain": "global",
        "reason": "deleted",
        "message": "Resource has been deleted"
      }
    ],
    "code": 410,
    "message": "Resource has been deleted"
  }
}

推奨されるアクション: syncToken パラメータまたは updatedMin パラメータについては、ストアをワイプして再同期します。詳細については、リソースを効率的に同期するをご覧ください。すでに削除されたイベントについては、これ以上の対応は必要ありません。

412: 前提条件を満たしていません

If-Match ヘッダーで指定された ETag が、リソースの現在の ETag に対応しなくなりました。

{
  "error": {
    "errors": [
      {
        "domain": "global",
        "reason": "conditionNotMet",
        "message": "Precondition Failed",
        "locationType": "header",
        "location": "If-Match"
      }
    ],
    "code": 412,
    "message": "Precondition Failed"
  }
}

推奨される対応策: エンティティを再取得して、変更を再適用します。詳細については、特定バージョンのリソースを取得するをご覧ください。

429: リクエストが多すぎます

rateLimitExceeded エラーは、ユーザーが一定時間内に送信したリクエストが多すぎる場合に発生します。

{
  "error": {
    "errors": [
      {
        "domain": "usageLimits",
        "reason": "rateLimitExceeded",
        "message": "Rate Limit Exceeded"
      }
    ],
    "code": 429,
    "message": "Rate Limit Exceeded"
  }
}

推奨される対応: rateLimitExceeded エラーは 403 または 429 のエラーコードを返します。これらは機能的に類似しているため、指数バックオフを使用して同じ方法で処理する必要があります。また、アプリが割り当ての管理のベスト プラクティスに準拠していることを確認してください。

500: バックエンド エラー

リクエストの処理中に予期しないエラーが発生しました。

{
  "error": {
    "errors": [
      {
        "domain": "global",
        "reason": "backendError",
        "message": "Backend Error"
      }
    ],
    "code": 500,
    "message": "Backend Error"
  }
}

推奨される対応: 指数バックオフを使用します。