Skip to main content

Error handling

Cloud API error responses use Content-Type: application/problem+json. Branch on type. title, detail, and hint are the human-readable text.

A missing token on GET /iam/clients/me is a different body, Content-Type: application/json:

{
  "message": "Authentication credentials were not provided.",
  "code": "not_authenticated"
}

Error response fields

Every Cloud API error body in this article includes these fields:

FieldDescription
typeStable code. Branch on this value.
titleFixed sentence for that type.
statusHTTP status code, repeated in the body.
detailWhat happened on this call.
hintWhat to do next.
request_idSame value as the X-Request-Id response header.
trace_idTrace id. It is the second field of the traceparent response header.

Some bodies also include the fields below.

FieldWhen it appears
errorsvalidation-error. One item per invalid input: loc, code, detail, and sometimes ctx.
contextExtra data for the type. Resource errors include resource_type and resource_id. method-not-allowed includes allowed_methods.
exception_classPrevious name of the error. Branch on type.
messagePrevious text of the error.
invalid_fieldsPrevious field map on some validation responses. Read errors.

type, errors[].code, and loc stay the same in every language. exception_class stays the same as well.

unauthorized

A request with no Authorization header returns HTTP 401:

{
  "type": "unauthorized",
  "title": "The request has no valid credentials.",
  "status": 401,
  "detail": "The request has no API key and no token.",
  "hint": "Send the header 'Authorization: apikey <api_token>' with a valid token. If you have no token, create an API token first.",
  "request_id": "c5fc3b9e7a09a3661ee2a5c0f9d18674",
  "trace_id": "40dcb19aad763c6b66855e82d814b9c3",
  "exception_class": "UnauthorizedError",
  "message": "The request has no API key and no token."
}

detail identifies which credential failure this is:

detailCause
The request has no API key and no token.No Authorization header
The API key or the token is not valid.The header was sent, and the token is not valid

Create an API token when the account has none. Send it on later calls as Authorization: APIKey $GCORE_API_KEY.

validation-error

HTTP 400. errors lists each invalid input. loc is the path to that input. In the responses below it starts with body. code names the failed check.

A create-volume call with "source": "new-volume" and no size returns:

{
  "type": "validation-error",
  "title": "The request has invalid input.",
  "status": 400,
  "detail": "1 input is not valid.",
  "hint": "Correct each input in 'errors', then send the request again.",
  "request_id": "0f43199b2960322c34cb5b4c94d652b8",
  "trace_id": "53428bb45062e7df50bb06144538c2fd",
  "errors": [
    {
      "loc": ["body", "size"],
      "code": "missing",
      "detail": "The field is required."
    }
  ],
  "exception_class": "ValidationError",
  "message": "'size': The field is required.",
  "invalid_fields": {
    "new-volume": {
      "size": ["Field required"]
    }
  }
}

invalid_fields on this response is grouped under new-volume, the source value. errors[].loc is the path to read. Correct size, then send the call again. The same body sent again returns the same 400.

A body that is not JSON is also validation-error. The item then has "code": "json_invalid" and "loc": ["body"].

Another validation item can include ctx. An empty object sent to the same endpoint returned "code": "union_tag_not_found" and "ctx": {"discriminator": "'source'"}.

not-found

HTTP 404. A volume id that does not exist returns:

{
  "type": "not-found",
  "title": "The resource does not exist.",
  "status": 404,
  "detail": "The volume '00000000-0000-4000-8000-000000000001' does not exist.",
  "hint": "Check the ID, or list the volumes to find it.",
  "request_id": "fab9270b14372990f2c596fc67992aa6",
  "trace_id": "ed27d90f421793327f0a0768e2fdaa12",
  "context": {
    "resource_type": "volumes",
    "resource_id": "00000000-0000-4000-8000-000000000001"
  },
  "exception_class": "NotFoundError",
  "message": "The volume '00000000-0000-4000-8000-000000000001' does not exist."
}

context.resource_type and context.resource_id name the missing resource. Check the id, the project, and the region, then list that resource.

A path that matches no endpoint is also not-found, with no context, exception_class, or message:

{
  "type": "not-found",
  "title": "The resource does not exist.",
  "status": 404,
  "detail": "The URL does not match an endpoint.",
  "hint": "Check the URL.",
  "request_id": "e04bb04f06a8506dba5b687bb1df4fd5",
  "trace_id": "e4e650e2a4121cefbc03b45f549a1bbc"
}

method-not-allowed

HTTP 405. PATCH on the volume collection returns:

{
  "type": "method-not-allowed",
  "title": "The endpoint does not support the method.",
  "status": 405,
  "detail": "The endpoint does not support 'PATCH'.",
  "hint": "Use one of the methods in 'allowed_methods'.",
  "request_id": "d42d9a180a2268e3f9f9e3c1c89d8df5",
  "trace_id": "392f25fddd27c0183a4bb6c6a088cbae",
  "context": {
    "allowed_methods": ["GET", "POST"]
  }
}

This response has no exception_class or message. The Allow header on the same response is GET, POST, matching context.allowed_methods.

Language

Send Accept-Language to select the language of title, detail, and hint. The response sets Content-Language to that language and sends Vary: Accept-Language. With no Accept-Language, Content-Language is en.

ru, de, zh, and az each returned translated title, detail, and hint for an unknown URL. The same create-volume validation with Accept-Language: ru returns:

{
  "type": "validation-error",
  "title": "Запрос содержит недопустимые входные параметры.",
  "status": 400,
  "detail": "1 входной параметр недопустим.",
  "hint": "Исправьте каждый входной параметр в 'errors', затем отправьте запрос снова.",
  "request_id": "fb5fe140dc868b4233f489f7ae60044a",
  "trace_id": "7a0860c6f68acdd99a4bd5114721e503",
  "errors": [
    {
      "loc": ["body", "size"],
      "code": "missing",
      "detail": "Поле обязательно."
    }
  ],
  "exception_class": "ValidationError",
  "message": "'size': Поле обязательно.",
  "invalid_fields": {
    "new-volume": {
      "size": ["Field required"]
    }
  }
}

errors[].detail and message are Russian. invalid_fields stays English (Field required). type, code, and loc are unchanged.

Next step

typeAction
unauthorizedSend a valid API token in Authorization.
validation-errorCorrect every item in errors, then send the request again.
not-foundCheck the id in context, or check the URL when context is absent.
method-not-allowedCall again with a method from context.allowed_methods.

Include request_id when contacting CDB support.