处理 API 错误

Calendar API 会返回两级错误信息:

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

本页面的其余部分提供了日历错误的参考,以及有关如何在应用中处理这些错误的指导。

实现指数退避算法

Cloud API 文档很好地解释了指数退避算法以及如何将其与 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 流程,如使用 OAuth 2.0 向请求授权中所述。
  • 如果您在某个服务帐号中看到了此错误消息,请确认您已成功完成“服务帐号”页面中的所有步骤。

403:已超出用户速率限制

已达到 Play 管理中心的其中一项限制。

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

建议采取的措施

403:已超出速率限制

用户已达到每个日历或每个身份验证用户的 Google Calendar API 请求率上限。

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

建议操作rateLimitExceeded 错误可以返回 403 或 429 错误代码,目前它们在功能上类似,应使用指数退避算法以相同的方式响应。此外,请确保您的应用遵循管理配额中的最佳做法。

403:已超出日历使用限制

用户达到了 Google 日历限制之一,是为了保护 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,否则请使用 update 方法调用。

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

建议采取的措施:使用指数退避算法