API errors
Errors are returned as application/problem+json per RFC 7807. The shape is the same across endpoints, so one error handler is enough. What does need separating is a request that was rejected outright from an operation that was accepted and failed later.
The error body
The standard RFC 7807 members are present on every error response: type, title,
status, detail and instance. title and detail are
written for humans and may be reworded without notice — never parse them or compare them as strings.
On top of the standard members the API adds code: a stable machine-readable identifier of the specific
error condition. That is what your code should branch on. When there is no such identifier, the field is omitted.
code is declared on only one response today
In the current schema the type carrying code is declared on exactly one response — the 409
from VM creation, where code is insufficientCapacity. Every other error response is typed
with the base problem details shape that has no code. Write your handler so a missing field is
harmless: read code when present and fall back to the HTTP status when it is not.
Status codes
400— the request failed validation. The body carries anerrorsmap of field name to messages. Badsortsandfiltersland here too, for example a field the endpoint does not support.401— the request is not authenticated: no valid Keycloak session or bearer token.404— the resource was not found. Check that the identifiers in the path belong to the same project; a VM from another project looks missing.409— a state conflict. Most often another operation is already running on the resource.503— the endpoint is temporarily disabled. VM resize currently answers this for any input.
409 conflicts and what to do about them
409 covers several distinct situations, and each calls for a different reaction.
Busy with another operation. While an operation runs on a VM, network or address, other changes to the same resource are rejected. Wait until the resource's
statusleavescreating,updatingordeleting, then retry.Out of capacity. VM creation returns
codeset toinsufficientCapacity. Nothing is charged and no VM is created. Retry later or pick a smaller configuration — the configurations list shows this in advance throughavailabilityandmaxCount.Still in use. A project cannot be deleted while it owns VMs, networks or public IPs; an SSH key cannot be deleted while it is authorized on a VM; a public IP cannot be released while it is attached. Remove the dependency first.
A rejected request is not a failed operation
A 202 means the work was accepted. If it fails later there is no HTTP error to catch — the operation
record carries the outcome. Its status becomes Failed and failureCode says
why.
insufficientCapacity— no node could fit the requested configuration.timeout— the operation did not finish within its allotted time.internal— any other or unclassified cause.
Remember that a failure handled normally leaves the resource active. That means the resource's
status cannot tell you the outcome — read the operation. See
Statuses and lifecycle for the details.
What to log
Log status, code and instance from the error body, and for async failures the
operation id together with failureCode. An operation's currentState reads well for a human
but its set of values is not stable, so do not build conditions on it.
Related endpoints
/projects/{projectId}/vmsThe one endpoint whose 409 carries a code field.
/projects/{projectId}/operations/{operationId}Read the outcome and failureCode of an async operation.
/configurationsCheck capacity up front and avoid the 409.
/projects/{projectId}An example of 409 caused by remaining dependencies.