处理 API 错误

Google 日历 API 会返回两个级别的错误信息:

  • 标头中的 HTTP 错误代码和消息
  • 响应正文中的 JSON 对象,其中包含有助于您确定如何处理错误的更多详细信息。

本页的其余部分提供了日历错误的参考,并提供了一些关于如何在应用中处理这些错误的指南。

实现指数退避算法

Google Cloud Storage 文档 介绍了指数退避算法以及如何将其与 Google API 结合使用。

错误和建议的操作

本部分提供了每个列出的错误的完整 JSON 表示法,以及您可能需要采取的建议操作。

400:错误请求

用户错误。如果您未提供必填字段或参数、提供的值无效或提供的字段组合无效,则会发生此错误。

{
  "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:凭据无效

授权标头无效。 您使用的访问令牌已过期或无效。

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

建议的操作

403:已超出速率限制

用户已达到每个日历或每个经过身份验证的用户的 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: importEvents: 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:冲突

由于与请求的其他 批处理项存在操作冲突,因此无法执行 events.batch 操作中的批处理项。

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

建议的操作: 移除已完成和失败的项,然后在不同的 events.batch 或相应的单个事件操作中重试剩余的项。

410:已删除

syncTokenupdatedMin 参数不再有效。如果请求尝试删除已删除的事件,也可能会发生此错误。

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

建议的操作: 对于 syncTokenupdatedMin 参数,请清除存储并重新同步。如需了解详情,请参阅 高效同步资源。 对于已删除的事件,无需执行任何进一步的操作。

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

建议的操作: 使用指数退避算法