Skip to Content
Errors

Errors

Errors are RFC 9457 problem documents  served as application/problem+json:

{ "type": "https://braesystems.com/docs/errors/server-busy", "title": "Server busy", "status": 409, "detail": "A re-image is in progress. Rebooting now would leave the server without a working OS." }

Branch on type. It is a stable identifier; title and detail are prose and may be reworded.

Catalogue

type suffixStatusMeaning and what to do
unauthorized401Missing, malformed, revoked, or unknown API key. Check the Authorization: Bearer bs_live_… header.
forbidden403Authenticated, but not permitted.
not-found404No such resource in your account. See the note below.
invalid-request400The body or parameters failed validation. detail names the field.
invalid-ssh-key400The public key could not be parsed.
duplicate-ssh-key409A key with that fingerprint is already on the account.
server-busy409Another operation is already running on the server. Retry once it settles.
server-not-ready409The server’s state does not allow the operation.
unknown-image400No such image slug. See GET /api/v1/images.
rate-limited429Too many requests. Back off and retry.
internal500Something broke on our side. Retry; if it persists, contact us with the response.

Why 404 and not 403

A resource belonging to another account returns 404, exactly as a resource that does not exist does. This is deliberate: distinguishing the two would confirm that a given id exists somewhere, letting a caller enumerate other customers’ server and key ids by guessing.

For the same reason, passing an ssh_key_ids value that belongs to another account returns 400 invalid-request rather than 404.

Retrying

409 and 429 are worth retrying — the first once the current operation finishes, the second after a backoff. 500 is worth one or two retries.

400, 401, 403, and 404 will not change on retry; the request itself needs fixing.

Failed operations are not errors

A reboot or re-image that fails still returns 202 at request time — the request was accepted. The failure surfaces on the action:

{ "data": { "id": "6b5a4c3d-2e1f-4a9b-8c7d-6e5f4a3b2c1d", "kind": "reboot", "status": "failed", "error": "Server never left power state On after 10.0 minutes; the restart appears to have been ignored.", "simulated": false } }

Always check status when polling, not just the HTTP code.

Last updated on