layahost
Menu · Errors

Errors

layahost uses standard HTTP status codes and the same error bodies as the Jev API, so the Jev SDKs raise their usual exceptions.

Error format

Most errors have a detail object with a machine-readable error_type and a human-readable message:

Response · 401
{
  "detail": {
    "error_type": "authentication_error",
    "message": "Invalid or revoked API key."
  }
}

Validation errors (422) use the FastAPI format instead: detail is a list with one entry per problem, and loc is the path to the field. See Validation errors.

Branch on the status code and error_type. Messages are for people and may change.

Status codes

Statuserror_typeMeaningWhat to do
401authentication_errorThe API key is missing, invalid or revoked.Check the Authorization header and the key. Don't retry.
402insufficient_creditsYour prepaid balance doesn't cover this request.Top up. Don't retry until you have.
404not_found_errorThere is no endpoint at this path.Check the URL: paths start with /v1/, with no /api prefix.
405invalid_request_errorThe endpoint exists but not for this HTTP method.Use POST for /v1/decide and /v1/systemone, GET for the lists.
422(list)The request body is invalid.Fix the request. Don't retry.
429rate_limit_errorThis key sent too many requests this minute.Wait for the number of seconds in retry-after, then retry.
500api_errorAn unexpected error on our side.Retry with backoff. If it persists, contact support with the request ID.
503api_errorThe inference backend is unavailable or failed.Retry after retry-after seconds, with backoff.
529overloaded_errorAll inference capacity is busy.Retry after retry-after seconds, with backoff.

Requests rejected with 401, 402, 404, 405, 422, 429, 503 or 529 are not billed: if a request fails after it was charged, the charge is returned to your balance.

Authentication errors

A missing header and a bad key get different messages:

Response · 401
{
  "detail": {
    "error_type": "authentication_error",
    "message": "Missing API key. Send it as \"Authorization: Bearer <API_KEY>\"."
  }
}

See Authentication.

Insufficient credits

layahost is prepaid. When your balance can't cover a request, you get 402 with error_type insufficient_credits and a message with a link to the Billing page. A request is charged as a whole, so a /v1/systemone call with 10 questions needs credit for 10 decisions. We email you before you run out; set the threshold in Settings → Data & alerts. See Pricing & billing.

Unknown endpoints and methods

A path that doesn't exist gets 404, and a known path with the wrong method gets 405:

Response · 404
{
  "detail": {
    "error_type": "not_found_error",
    "message": "Unknown endpoint. See https://layahost.com/docs."
  }
}
Response · 405
{
  "detail": {
    "error_type": "invalid_request_error",
    "message": "Method not allowed for this endpoint."
  }
}

Validation errors

A body that is missing fields or has values of the wrong kind gets 422. Each entry has loc ("body" followed by the path to the field), msg and type:

Response · 422
{
  "detail": [
    {
      "loc": ["body", "type"],
      "msg": "The type field is required when template is not present.",
      "type": "value_error"
    },
    {
      "loc": ["body", "question"],
      "msg": "The question field is required when template is not present.",
      "type": "value_error"
    }
  ]
}

Problems inside a /v1/systemone question also carry the offending input and a ctx object with details, and type names the rule that failed:

Response · 422
{
  "detail": [
    {
      "type": "too_short",
      "loc": ["body", "questions", "q", "choice", "criteria"],
      "msg": "Dictionary should have at least 2 items after validation, not 1",
      "input": {"yes": null},
      "ctx": {
        "field_type": "Dictionary",
        "min_length": 2,
        "actual_length": 1
      }
    }
  ]
}

Option lists that don't fit the model's option budget (192 tokens for all names and descriptions of one question) also get 422, on ["body", "questions", "<name>", "criteria"] for /v1/systemone and on ["body", "options"] for /v1/decide. See Limits.

Rate limit errors

Each key may send 600 requests per minute. Over that, you get 429 with a retry-after header: the number of seconds until the window resets.

Response · 429
HTTP/1.1 429 Too Many Requests
content-type: application/json
retry-after: 38
x-request-id: req_0t9rn7vlp9c6tl5rgaeetoc8
x-typesafe-request-id: req_0t9rn7vlp9c6tl5rgaeetoc8

{
  "detail": {
    "error_type": "rate_limit_error",
    "message": "Rate limit of 600 requests per minute exceeded."
  }
}

See Rate limits.

Server and capacity errors

503 (api_error) means the inference backend was unavailable or failed to answer. 529 (overloaded_error, message “Inference capacity is saturated, retry shortly.”) means all inference capacity is busy. Both are temporary and both come with retry-after: 1:

Response · 503
HTTP/1.1 503 Service Unavailable
content-type: application/json
retry-after: 1
x-request-id: req_guglin9qhthimpisgz5umdhp
x-typesafe-request-id: req_guglin9qhthimpisgz5umdhp

{
  "detail": {
    "error_type": "api_error",
    "message": "Inference backend is unavailable, retry shortly."
  }
}

An unexpected error on our side gets 500 with error_type api_error, in the same format.

Retries

  • Retry 429, 503 and 529 after the number of seconds in retry-after, and back off exponentially if the error repeats. Retry 500 with backoff.
  • Don't retry 401, 402, 404, 405 or 422: the same request will fail again.
  • Retrying 429, 503 and 529 is safe. Those requests were not billed and changed nothing.

The Jev SDKs do this for you. By default, both retry 408, 429 and every 5xx status up to twice, and honour retry-after. There is a fetch-based retry loop in Code examples.

SDK exceptions

StatusPython (typesafe_sdk)JavaScript (@typesafe-ai/sdk)
401TypeSafeAuthenticationErrorAuthenticationError
402, 405TypeSafeAPIErrorAPIError
404TypeSafeNotFoundErrorNotFoundError
422TypeSafeUnprocessableEntityErrorUnprocessableEntityError
429TypeSafeRateLimitErrorRateLimitError
500, 503, 529TypeSafeInternalServerErrorInternalServerError

Every class in the table extends the SDK's base API error, TypeSafeAPIError or APIError, which has the HTTP status, the parsed body and the request ID (request_id in Python, requestId in JavaScript).

Request IDs

Every response from /v1/, successful or not, carries a request ID such as req_3rmqhpttolpzez0quj0bt42x in two headers with the same value: x-request-id, and x-typesafe-request-id for the Jev SDKs. Successful decisions also include it in the body, as request_id on /v1/decide and meta.request_id on /v1/systemone.

Requests that reach the model are listed in Logs under the same ID. Include the ID when you contact support.