Guides

Errors and limits

Every failure answers with the same document and a code that does not change. Branch on the code, show the detail.

The error document

Errors are RFC 9457 problem documents, served as application/problem+json with the matching HTTP status.

422 Unprocessable Entity
{
  "type": "about:blank",
  "title": "Unprocessable Entity",
  "status": 422,
  "code": "validation_failed",
  "detail": "the request is invalid",
  "errors": [
    { "field": "port", "message": "must be between 1 and 65535" }
  ]
}
FieldMeaning
codeWhat kind of error this is, as a stable identifier. This is what code should test.
detailA sentence for a person, saying what went wrong and, where it helps, what to do.
statusThe HTTP status, repeated.
errorsOn validation errors only: one entry per invalid field, with its name and message.
type, titleAlways about:blank and the status's standard phrase.

Codes

The codes below can come from any endpoint. Those specific to one endpoint are listed with its responses in the reference.

StatusCodeWhen
400(various)The request cannot be acted on as it is. The code names why, per endpoint: passkey_expired, not_impersonating…
401unauthenticatedNo credential, or one that is unknown, expired or revoked.
401invalid_credentialsThe email or password is wrong. Deliberately does not say which.
401invalid_codeThe two-factor or recovery code is wrong, or was already used.
401mfa_requiredThe session has passed the password and waits for its second factor.
403forbiddenThe caller is known but its role is too low, or the request comes from another site.
403confirmation_requiredA secret is being read back: the session must confirm its identity first.
403signups_closedNew accounts cannot be created right now.
403suspendedThe account was suspended by the platform's operators; the detail says why.
404not_foundNo such thing, or nothing the caller may see. The two are not told apart, so names cannot be probed.
409(various)The request conflicts with what exists: name_taken, bucket_not_empty, tunnel_limit, not_in_progress… Listed on each endpoint.
422validation_failedOne or more fields are invalid. `errors` lists each field and what is wrong with it.
429rate_limitedToo many attempts. `Retry-After` gives the seconds to wait.
501not_configuredThis deployment runs without that product: no storage engine, no node for deployments, no GitHub App.
503maintenanceThe platform is closed for maintenance. What is deployed keeps being served; the API comes back by itself.
500internalA fault on the platform's side. Nothing in the detail is meant to be parsed.

What is safe to retry

  • GET, PUT and DELETE can be repeated: asking twice leaves things as asking once.
  • Creating by name (a service, a bucket, a tunnel with a name) is safe to repeat too: the second attempt answers 409 name_taken rather than making a second one. Tunnel creation accepts reuse: true to get the existing one back instead.
  • Starting a deployment is not: each call queues one.
  • On 429, wait for Retry-After. On 5xx and network failures, retry with increasing pauses.

Limits

LimitValue
Request body1 MiB of JSON. Objects go to the storage endpoint, which has no such limit.
Request duration30 seconds.
Sign-in attempts30 per address in 5 minutes; 10 per email in 15 minutes.
Second-factor and confirmation attempts8 per account in 10 minutes.
Sign-ups10 per address per hour.
Services per workspaceShown in the 409 service_limit answer when reached.
Tunnels per workspace100.
Machines per workspace50.
Buckets per workspace50, with 20 access keys each.
Variables per serviceShown in the validation error when exceeded.
Operations signed at once1,000 object URLs per call, valid from a minute to a week.
Runtime logThe most recent 5,000 lines per service.

Listings that can grow without bound (requests, events, audit entries) take a limit and return the newest first; the reference says how each continues.