Skip to content

API error codes

Updated

Errors use a stable code for programs and a human-readable message:

{
"code": "INVALID_STATE",
"message": "VM 'demo-api-vm' in state Running does not allow this operation"
}

Callers should branch on code, not message.

Most Virtainer application errors use the JSON envelope above. A few responses are intentionally different:

StatusContent typeBodyDescription
204 No ContentnoneemptySuccessful lifecycle and delete operations do not return JSON.
4xx or 5xxJSON{ "code": "...", "message": "..." }Standard Virtainer application error.
422 Unprocessable Entitytextplain textAxum rejected the JSON body before the handler ran, usually because a required field was missing or a value had the wrong type.
CodeMeaning
BAD_REQUESTThe request body or parameter is invalid.
UNAUTHORIZEDThe bearer token is missing or invalid.
FORBIDDENThe key is valid, but the endpoint is outside the API key allowlist, or a read-only key attempted a mutation.
NOT_FOUNDThe resource does not exist.
ALREADY_EXISTSA VM or template with that id already exists.
CONFLICTA related operation is already in progress, such as an AppVM image import.
INVALID_STATEThe requested action does not match the current VM state.
CH_ERRORCloud Hypervisor returned an error.
NETWORK_ERRORHost network setup or realization failed.
STORAGE_ERRORImage, disk, qsd, or storage work failed.
INTERNALThe host returned an unexpected server error.
StatusMeaning
400 Bad RequestThe handler understood the JSON but rejected a field, combination, or host-side precondition.
401 UnauthorizedMissing or invalid bearer token.
403 ForbiddenValid key, but insufficient scope or endpoint is outside the API key allowlist.
404 Not FoundResource id does not exist.
409 ConflictDuplicate id, invalid lifecycle state, capacity/admission conflict, or in-progress operation.
422 Unprocessable EntityJSON deserialization failed before handler validation. Body is plain text.
500 Internal Server ErrorHost-side storage, network, Cloud Hypervisor, registry, or unexpected internal failure.
  • Use a stable vm_id for create calls so retries do not create duplicate machines.
  • Treat 204 No Content from lifecycle actions as accepted by the host, not as proof that the guest is ready. Read GET /api/vms/{id} afterward.
  • On ALREADY_EXISTS, read GET /api/vms/{id} and compare it with your intended machine.
  • On INVALID_STATE, read the current state before trying another action.
  • On 5xx or CH_ERROR, mark the operation as unknown and read state before retrying. Do not assume failed mutations were fully rolled back.