# Error catalog

> Every error code the API answers, with its HTTP status and what to do about it. Generated from the contract's code lists.

Every error of the API is a JSON object with a sentence and a stable code: `{ "error": "name already taken", "code": "name-taken" }`. Branch on `code`, show `error`. A code your program does not know should fall back on the HTTP status; the generic code of a status is listed first. See [REST API basics](https://docs.rytiv.com/reference/api-basics.md) for the request and response format.

## Generic codes

One per HTTP status. A route answers one of these when it has nothing more specific to say.

| Status | Code | Meaning |
| --- | --- | --- |
| 400 | `bad-request` | The request is malformed or a field is out of range. `error` names every field; `issues` lists them. |
| 401 | `unauthenticated` | No API key, or one that does not work (unknown, revoked or expired). |
| 403 | `forbidden` | The key may not do this. |
| 404 | `not-found` | Not found, or not yours. An object of another organization answers like one that does not exist. |
| 409 | `conflict` | The request conflicts with the current state. |
| 410 | `gone` | The object existed and is gone. |
| 413 | `too-large` | The body is larger than the route accepts. |
| 422 | `unprocessable` | The request is well-formed but cannot be carried out as it is. |
| 426 | `upgrade-required` | The route needs a WebSocket upgrade; use the CLI. |
| 429 | `rate-limited` | Too many requests; wait for `Retry-After` and try again. |
| 500 | `internal` | Something failed on Rytiv's side. The sentence carries a reference you can quote. |
| 501 | `not-implemented` | Not available on this installation. |
| 502 | `upstream-failed` | A host, the object store or a connected service failed. |
| 503 | `unavailable` | Not possible right now; try again shortly. |
| 504 | `upstream-timeout` | A host or a connected service did not answer in time. |

## Codes shared by several routes

| Status | Code | Meaning |
| --- | --- | --- |
| 409 | `name-taken` | The name is used somewhere on Rytiv (an app, a database, a volume or a bucket). |
| 409 | `already-exists` | You already have it; an idempotent create may treat this as done. |
| 400 | `name-reserved` | The platform keeps this name (for example `api`, `console`, `docs`, `www`, and every name that is `rytiv` or starts with `rytiv-`). |
| 403 | `org-suspended` | The organization was suspended by the operator. |
| 403 | `delegation-refused` | `X-Rytiv-Org` names an organization this key may not act for. |
| 403 | `creator-proof` | Creating an organization needs the console's signed proof of the person. |
| 403 | `token-scope` | The key's scopes do not cover this route, this mail domain or this upgrade. The sentence names the scope needed. |
| 503 | `no-capacity` | No host in the region has room for the machine right now; try again. |
| 503 | `lease-held` | Another host still holds the volume or checkpoint; try again shortly. |
| 503 | `create-failed` | The host could not create the machine (image, start command or port). The sentence says which. |
| 503 | `database-unavailable` | The platform database cannot be reached right now; retry after `Retry-After`. |
| 408 | `wait-timeout` | The wait ran out before the machine reached the state; ask again. |
| 409 | `not-a-copy` | The database is neither a fork nor a branch; its URL came with its create answer. |
| 409 | `not-ready` | The copy is still restoring, or failed; there is nothing to hand out yet. |
| 409 | `url-handed-out` | The URL of this copy was handed out already. It leaves the platform exactly once. |
| 403 | `agent-token-production-readonly` | An agent token of class `production` may read; a change needs a person. |
| 403 | `agent-token-production-data` | An agent token of class `production` without `prodDataRead` may not read what production holds. |
| 403 | `agent-token-credential` | No agent token mints, reveals or revokes a credential, or administers the organization. |
| 403 | `agent-token-app-scope` | The request is about an app outside the token's list, or about no app at all. |
| 403 | `agent-token-route-unknown` | A route the agent rules do not know is refused. |
| 403 | `agent-token-delegation` | An agent token acts in its own organization only. |
| 503 | `agent-audit-unavailable` | The audit record of the action could not be written, so the action did not run; ask again shortly. |
| 403 | `org-limit-computers` | The organization has as many computers as it may have. The body carries `limit` and `current`. Delete one, or contact us for more. |
| 403 | `org-limit-apps` | The organization has as many apps as it may have (computers included). The body carries `limit` and `current`. |

## Machine actions

Answered by `POST /v1/machines/:id/:action` and a machine create when the host could not start the machine.

| Status | Code | Meaning |
| --- | --- | --- |
| 503 | `start-interrupted` | The start was interrupted on the host. |
| 503 | `guest-exited` | The machine's process ended during the start. |
| 503 | `port-timeout` | The machine did not answer on its port in time. |
| 503 | `no-capacity` | No host in the region has room for the machine right now; try again. |
| 503 | `host-refused` | The host refused the action. |
| 503 | `host-unreachable` | The host did not answer. |
| 409 | `machine-busy` | Another operation on the machine is in progress; try again. |
| 503 | `create-failed` | The host could not create the machine (image, start command or port). The sentence says which. |

## Rollbacks

Answered by `POST /v1/apps/:name/rollback`.

| Status | Code | Meaning |
| --- | --- | --- |
| 404 | `release-not-found` | No release with that version or id. |
| 409 | `rollback-target-current` | That release is the one that runs. |
| 409 | `rollback-same-build` | That release runs the same build as the current one. |
| 409 | `rollback-target-never-live` | That release never went live, so there is nothing to bring back. |
| 409 | `release-artifact-gone` | The release's image is no longer available. |
| 409 | `no-previous-release` | There is no earlier release that went live. |
| 409 | `rollback-not-for-resources` | The app backs a database; databases are restored, not rolled back. |
| 409 | `rollback-needs-machine-config` | The app has no machine whose settings a rollback could reuse. |
| 409 | `deploy-in-flight` | Another deploy of this app is running. |

## Credit and billing

Answered by the routes under `/v1/billing`.

| Status | Code | Meaning |
| --- | --- | --- |
| 402 | `credit-blocked` | The organization's credit is at zero: nothing new starts until a top-up. Reads, stops and the billing routes still answer. |
| 409 | `no-customer` | No payment relationship yet; a first top-up creates it. |
| 403 | `billing-console-only` | A billing change is made in the console by an admin, not with an API key. |
| 409 | `not-prepaid` | The organization has no credit account; only org creation or an operator's grant starts prepaid credit. |

## Computers

Answered by the viewer and control routes of a computer.

| Status | Code | Meaning |
| --- | --- | --- |
| 409 | `not-a-computer` | The machine is not a computer (it has no `COMPUTER_VIEW_KEY`), or it is a console or job machine. |
| 409 | `machine-stopped` | The machine is stopped; start it first. |
| 503 | `not-placed` | The machine has no host yet. |
| 503 | `view-key-unreadable` | The computer's key cannot be decrypted right now. |
| 409 | `view-key-too-short` | The computer's key is too short; the image would refuse to start with it. |
| 409 | `several-machines` | Control needs exactly one machine; the app has several. |
| 409 | `control-held` | Somebody else holds control; the body names `heldBy`, `until` and `leaseId`. Use `force` to take it. |
| 409 | `control-busy` | Another change of control is in progress; try again after `Retry-After`. |
| 409 | `computer-control-missing` | The machine runs a computer image from before control leases; deploy it again. |
| 409 | `guest-agent-absent` | The machine has no guest channel; it was created before shell sessions existed. Deploy it again. |
| 503 | `guest-channel-off` | The guest channel is switched off on the machine's host. |
| 503 | `guest-unreachable` | The guest did not answer; try again after `Retry-After`. |
| 502 | `guest-failed` | The control tool in the machine ran and failed. |
| 409 | `managed-service` | A managed database; its machine is not opened to a shell. |
| 503 | `resource-check-failed` | Could not tell whether the machine backs a managed database; try again. |

## Shell sessions

Answered when a shell, a tunnel or a file transfer into a machine is refused (`ry exec`, `ry ssh`, `ry proxy`).

| Status | Code | Meaning |
| --- | --- | --- |
| 404 | `machine-not-found` | No such machine in your organization. |
| 409 | `console-machine` | The machine is a console or job machine; it takes no shell. |
| 409 | `managed-service` | A managed database; its machine is not opened to a shell. |
| 503 | `resource-check-failed` | Could not tell whether the machine backs a managed database; try again. |
| 409 | `machine-stopped` | The machine is stopped; start it first. |
| 409 | `machine-suspended-no-wake` | The machine is suspended and cannot be woken for this. |
| 503 | `machine-not-placed` | The machine has no host yet. |
| 429 | `too-many-sessions` | The machine has as many shell sessions open as it may. |
| 503 | `host-unavailable` | The machine's host is not reachable right now. |
| 503 | `audit-unavailable` | The audit record of the session could not be written, so it was not opened. |
| 503 | `exec-disabled` | Shell sessions are switched off on this installation. |
| 409 | `guest-agent-absent` | The machine has no guest channel; it was created before shell sessions existed. Deploy it again. |
| 504 | `guest-agent-timeout` | The guest did not answer in time. |
| 409 | `guest-agent-version` | The guest's agent is too old for this; deploy the machine again. |
| 502 | `guest-agent-protocol` | The guest answered something the platform did not expect. |
| 502 | `host-error` | The host failed to open the session. |
| 504 | `host-timeout` | The host did not answer in time. |

## Validation errors

A request that breaks a schema answers `400` with the code `bad-request`. The `error` sentence names every field that was wrong (`invalid request: memoryMb: Too big: expected number to be <=16384`), and `issues` carries the same problems as a list, one entry per field, each with `path` and `message`. Fix every named field at once; the server reports them all in one answer.
