API エラーの処理

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

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

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

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

Cloud APIs のドキュメントでは、指数バックオフと 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"
 }
}

推奨される対応:

403: User Rate Limit Exceeded

デベロッパー コンソールのいずれかの上限に達しました。

{
 "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

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

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

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

403: Calendar usage limits exceeded

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

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

推奨される対応:

403: Forbidden for non-organizer

予定の更新リクエストで、主催者以外のコピーで共有予定のプロパティを設定しようとしています。共有プロパティ(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: importEvents: update を使用していて、リクエストに共有プロパティが含まれていない場合は、デフォルト値に設定しようとしているのと同じです。代わりに Events: patch の使用を検討してください。
  • リクエストに共有プロパティがある場合は、主催者のコピーを更新する場合にのみ、これらのプロパティを変更しようとしていることを確認してください。

404: 見つかりません

指定されたリソースが見つかりませんでした。これにはいくつかの原因が考えられます。 次に例を示します。

  • リクエストされたリソース(指定された ID)が存在しない場合
  • ユーザーがアクセスできないカレンダーにアクセスする場合

    { "error": { "errors": [ { "domain": "global", "reason": "notFound", "message": "Not Found" } ], "code": 404, "message": "Not Found" } }

提案されたアクション: 指数バックオフを使用します。

409: The requested identifier already exists

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

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

提案されたアクション: 新しいインスタンスを作成する場合は、新しい ID を生成します。それ以外の場合は、 update メソッド呼び出しを使用します。

409: Conflict

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

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

提案されたアクション: 正常に完了したバッチ処理されたアイテムと、確実に失敗したバッチ処理されたアイテムをすべて除外し、残りのアイテムを別の events.batch または対応する単一のイベント オペレーションで再試行します。

410: 存在しません

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"
 }
}

提案されたアクション: 指数バックオフを使用します。