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 2.0으로 요청 승인에 설명된 대로 사용자에게 OAuth 흐름을 안내합니다.
  • 서비스 계정에 대해 이 오류가 표시되면 서비스 계정 페이지에서 모든 단계를 완료했는지 확인하세요.

403: 사용자 비율 제한 초과

Play Console에서 한도 중 하나에 도달했습니다.

{
 "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 Calendar 한도 중 하나에 도달했습니다.

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

권장 조치:

403: 비주최자에게 금지됨

이벤트 업데이트 요청에서 주최자의 속성이 아닌 사본에서 공유된 이벤트 속성 중 하나를 설정하려고 합니다. 공유 속성 (예: guestsCanInviteOthers, guestsCanModify, guestsCanSeeOtherGuests)은 주최자만 설정할 수 있습니다.

{
 "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: patch를 사용하는 것이 좋습니다.
  • 요청에 공유 속성이 포함된 경우 주최자의 사본을 업데이트하는 경우에만 이러한 속성을 변경하려고 해야 합니다.

404: 찾을 수 없음

지정된 리소스를 찾을 수 없습니다. 이는 여러 가지 경우에 발생할 수 있습니다. 예를 들면 다음과 같습니다.

  • 요청된 리소스 (제공된 ID 포함)가 존재하지 않을 때
  • 사용자가 액세스할 수 없는 캘린더에 액세스할 때

    { "error": { "errors": [ { "domain": "global", "reason": "notFound", "message": "찾을 수 없음" } ], "code": 404, "message": "찾을 수 없음" } }

권장 조치: 지수 백오프를 사용하세요.

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: 사라짐

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

권장 조치: 지수 백오프를 사용하세요.