Errors
Reference for the REST API error format, the status codes and error codes that it returns, rate limiting, and which errors you can safely retry.
When a request fails, the API returns an HTTP error status and a JSON body that describes the error. This reference lists the format, the codes, and how to handle them.
Error format
{
"code": "VALIDATION_FAILED",
"message": "2 fields failed validation: name, sizeGb",
"field": "name",
"details": {
"errors": [
{ "field": "name", "code": "string_too_short", "message": "String should have at least 1 character" },
{ "field": "sizeGb", "code": "missing", "message": "Field required" }
]
}
}| Field | Present | Meaning |
|---|---|---|
code | Always | A machine-readable error code from the tables below. Branch on this field. |
message | Always | A description in English for people. Don't parse it; use code in your program. |
field | When the error is about one request field | The name of that field, such as name or Idempotency-Key. |
details | When there is more context | Structured data that depends on the code, for example the list of resources that block a delete. |
retryable | Only when its value is true | Sending the identical request again can succeed. When the field is missing, it's false. |
The API doesn't use 400 Bad Request: a request that doesn't match the operation's schema returns 422 Unprocessable Entity.
Status codes and error codes
| Status | Code | Meaning | What to do |
|---|---|---|---|
400 | IDEMPOTENCY_KEY_REQUIRED | A POST request that creates a resource, sent with an API token or a service account key, has no Idempotency-Key header. | Send the header with a new UUID, and the same UUID when you retry. See Idempotent requests. |
401 | UNAUTHENTICATED | The credential is missing, wrong, expired, or revoked. | Check the Authorization header. See Authenticate with API tokens. |
403 | FORBIDDEN | You aren't allowed to do this. details.reason, when present, says why. | See Troubleshooting. |
403 | MFA_STEP_UP_REQUIRED | The operation needs a recent two-factor verification in your console session. | Verify with your authenticator app in the console, and try again. |
403 | MFA_SETUP_REQUIRED | The operation needs two-factor authentication, and your account has none. | Set up two-factor authentication. |
403 | INTERACTIVE_SESSION_REQUIRED | The operation can't be done with an API token or a service account key. | Do it in the console. |
404 | NOT_FOUND | The resource doesn't exist, or you can't access it. The API doesn't tell these two cases apart. | Check the ID and the project. |
405 | METHOD_NOT_ALLOWED | The path exists, but not with this method. | Check the method in the API reference. |
409 | CONFLICT | The request conflicts with the current state, for example a name that's taken or an action that's already running. | Read the resource, and resolve the conflict. If retryable is true, retry later. |
409 | QUOTA_EXCEEDED | The request would exceed a quota of your subscription, or a product limit such as the number of keys of a service account. For a subscription quota, the message names the resource, its limit and usage, and the quota ID. | Free up resources. For a subscription quota, you can also request an increase. See Quotas. |
409 | CAPACITY_UNAVAILABLE | The region can't place the request right now. | Retry later, or choose another size. This error is retryable. |
409 | DEPENDENCY_BLOCKED | Other resources depend on this one. details lists them, for example the instance that a volume is attached to. | Remove the dependencies first. |
409 | LOCKED | The resource can't be changed, for example a built-in role. | None; the resource stays as it is. |
409 | DELETION_PROTECTED | Deletion protection is on. | Turn deletion protection off, and delete again. |
409 | ROOT_VOLUME_WOULD_BE_DELETED, ATTACHED_VOLUME_WOULD_BE_DELETED | Deleting the instance would also delete a volume that must be kept, so the platform refused the delete. | See Troubleshoot virtual machines. |
412 | PRECONDITION_FAILED | The If-Match value doesn't match the resource's current version, or a required If-Match header is missing. | Read the resource again, and repeat the change with its new ETag. |
422 | VALIDATION_FAILED | The request isn't valid. field and details.errors name the problems. | Fix the request. See Validation errors. |
429 | RATE_LIMITED | You sent too many requests. | Wait for the number of seconds in the Retry-After header. See Rate limiting. |
500 | INTERNAL | An unexpected error occurred. | Retry later. If it persists, report it with the X-Request-Id. |
502 | PROVIDER_ERROR | The cloud accepted the work, and it failed there, for example an image that can't boot. The error isn't marked retryable. | Read the message, and change the request. |
502 | INTERNAL with "retryable": true | The API gateway couldn't reach a service. | Retry with backoff. |
503 | PROVIDER_UNAVAILABLE | A cloud service is temporarily unreachable. | Retry with backoff. This error is retryable. |
Some requests also return 404 Not Found for a feature that the region doesn't offer, for example when you request encryption at rest where the region can't provide it. The message names the feature and the region. Retrying can't change this answer.
Imported projects
These codes appear only for projects that the platform operator imported for you, with their existing resources:
| Status | Code | Meaning |
|---|---|---|
409 | IMPORTED_PROJECT_ACK_REQUIRED | Deleting the project deletes the resources that came with the import. The request must set acknowledgeImportedProjectDestruction to true to confirm it. |
403 | IMPORTED_PROJECT_PROTECTED | For a period after the import, you can't delete the project. details.protectedUntil says until when. |
409 | IMPORTED_PROJECT_IMPORT_INCOMPLETE | The import isn't finished, so the project can't be deleted. |
409 | IMPORTED_PROJECT_RELEASE_IN_PROGRESS | The operator is releasing the project, or a release failed. |
409 | IMPORTED_BACKUP_PLAN_READ_ONLY | The backup plan holds the backups that came with the import. You can read it and restore from it, but you can't change it. |
Validation errors
A 422 Unprocessable Entity response for an invalid request lists every problem at once in details.errors. Each entry has:
field: the field's path in the request, with dots between levels, ornullwhen the problem concerns the body as a whole.code: the kind of problem, such asmissingorstring_too_short.message: a description in English.
The top-level field describes the first entry, and message names every field. Fix all the listed fields before you send the request again.
Rate limiting
The API gateway limits how fast each credential can send requests. Every API token, service account key, and console session has its own limit, and requests without a credential are limited by source IP address. The limit allows short bursts above the sustained rate.
For an API token or a service account key, the limit applies per credential and also per tenant, over all of the tenant's credentials together. Every response to such a request carries these headers:
| Header | Value |
|---|---|
X-RateLimit-Limit | The number of requests that the current window allows. |
X-RateLimit-Remaining | The number of requests left in the current window. |
X-RateLimit-Reset | The number of seconds until the window resets, at least 1. |
When you exceed the limit, the gateway answers 429 Too Many Requests with the code RATE_LIMITED, "retryable": true, and a Retry-After header with the number of seconds to wait, at least 1. Wait at least that long before you send the next request.
This limit applies to requests to the REST API. For the limits of application credentials, see OpenStack API limits.
Errors in asynchronous operations
When the work of a 202 Accepted request fails, the operation's state becomes FAILED, and its error field contains an error in the format above. An operation that succeeded can carry a warning in the same format, when something that you requested couldn't be delivered. See Synchronous and asynchronous requests.
Responses from the network in front of the API
During a deployment, a proxy in front of the API can answer 500, 502, 503, or 504 with a body that isn't in the error format above, such as plain text. Such a response means that your request didn't reach the API. Retry it with backoff and the same Idempotency-Key.
Retry errors
- Retry when the response has
"retryable": true, and after a500,502,503, or504response that isn't in the error format. Send the sameIdempotency-Keyagain. See Idempotent requests. - Wait longer before each retry, for example 1, 2, 4, and then 8 seconds. After a
429response, wait at least theRetry-Aftertime. - Don't retry other
4xxerrors unchanged. Fix the request, the credential, or the state of the resource first.