Skip to content

Errors

Every refusal has the same shape: an HTTP status, and a JSON body with a fixed error code and a fixed sentence.

{
"error": "role_required",
"message": "this needs the client_admin role"
}
  • error is one of a fixed set, below. Branch on it, not on the message.
  • message is a fixed sentence for people. It never carries a key, a token, a body, or the value that was refused.
  • Some refusals add fields: parameter names the query parameter that was wrong, attribute the body field, limit and retry_after the limit that was reached.
  • A refusal is sent with Cache-Control: no-store, and with Retry-After where waiting will help.
Code Means Do
bad_query A path or query parameter, or a body field, is missing or not valid Fix the request. parameter says which, where it can

LightHouse answers a request that fails validation with 400 bad_query, never with 422.

Code Status Means Do
unauthenticated 401 No session and no valid key: missing, revoked, expired, or from another tenant Sign in, or issue a key in this tenant
mfa_required 403 The session does not prove a second factor Sign in again with a second factor
not_authorised 403 This identity has no grant in this tenant Ask a client_admin for access
role_required 403 The route needs a higher role See Roles
person_required 403 The route acts only for a signed-in person; a machine key never can Do it in LightHouse, as a person
commands_disabled 403 This command type is not switched on for your tenant A client_admin switches it on under Setup and admin → Commands
managed_by_aal 403 This provider connection is managed by Atlantic Ask Atlantic to change it
assistant_off, avatars_off 403 The feature is switched off for your tenant A client_admin switches it on
Code Means
not_found No such resource in your tenant
unknown_client No tenant at this address
flow_not_found A connector approval has expired (after 15 minutes); start again
Code Means
version_conflict What you are changing changed since you read it. Read it again, then write
conflict That already exists
connector_coming The connector is not built yet. See Connect your estate
route_unavailable That way of connecting is not available for this connector yet
adoption_closed The marketplace listing is not open to new adoption
details_required, invoice_terms, invoice_collection, no_customer, no_platform_price, invoice_not_open, nothing_pending, mirror_not_needed Billing: the step you asked for does not apply to your tenant’s terms or state; the message says why
Code Means
invalid The body is not a JSON object, is too large, or a field’s value is not allowed. attribute names the field
guard_rail The change breaks a rule LightHouse fixes, such as a key’s expiry or the staff role. rule names it
provider_refused The provider would not accept the credential or approval; the message names the provider
secret_refused A field that should hold an identifier looks like a credential
Code Means Do
assistant_capped The assistant has reached its limit Wait, or raise its limit

See Rate limits.

Code Status Means Do
internal 500 A fault on our side. Nothing was returned Retry later; tell Atlantic if it persists
stripe_failed 502 The payment provider did not accept the request; nothing was charged Retry
deployment_waking 503 Your ephemeral deployment is waking (“Waking your deployment…”) Retry after Retry-After (5 seconds)
tier_b_unavailable 503 Your content cannot be read in place right now: your deployment’s content reader is not connected Check the reader is running
provider_unavailable 503 The provider could not be reached Retry shortly
secret_store_unavailable 503 Your tenant’s key is not available, so a credential cannot be sealed Retry; tell Atlantic if it persists
commands_unavailable, assistant_unavailable, avatars_unavailable, billing_unavailable, exports_unavailable, identity_unavailable 503 That part of LightHouse is not set up where your tenant runs, or not reachable Retry later; tell Atlantic if it persists

A handler command that LightHouse accepted can still be refused by your deployment. That refusal is not an HTTP error: the command’s status becomes refused, with a reason from a fixed set, such as type-disabled, role, not-an-approver, bounds, raise-not-allowed, not-waiting, evidence-changed or gate-not-passed. Read it with GET /api/v1/commands/{command_id}. See Handlers.

A tool refusal arrives as a tool error carrying the same sentence, for example for role_required. Any other failure arrives as a generic message that quotes nothing. See MCP.