Errors
How Telmoni reports errors on the API and in the console: problem documents (RFC 9457), error types, status codes, and the two the machine host's door mints.
Telmoni reports API and console errors using Problem Details for HTTP APIs
(RFC 9457, sent as
application/problem+json). Each problem document carries a stable URI type
your code can branch on.
The shape of an error
{
"type": "/errors/authz/insufficient-role",
"title": "insufficient role",
"status": 403,
"detail": "required admin, have member"
}typeis a URI that identifies the problem kind. It never changes between deployments.titleis a short, human-readable summary of the problem type.statusis the HTTP status code, repeated inside the body.detailis human-readable and explains this specific occurrence. Some errors carry none, so treat it as optional.- Additional keys may appear on specific error types, as noted below.
Error types
| Type | Status | Means | Extra fields |
|---|---|---|---|
/errors/auth/unauthenticated | 401 | You are not signed in, your session was ended, or your account is being deleted; on the CLI's lanes, also a request that carried no credential. | |
/errors/auth/token-expired | 401 | Your session has expired. Sign in again. | |
/errors/auth/invalid-token | 401 | The credential sent is not valid, or the API got none. | |
/errors/auth/service-credential-rejected | 401 | One of Telmoni's services refused another's credential. This is Telmoni's fault, not yours. Only the console's own calls to the server meet it: the API, the CLI's lanes and ingest take no service credential. | |
/errors/auth/identity-unavailable | 503 | Telmoni could not check who you are right now, because the identity provider's keys or its own identity service could not be reached. Try again shortly. | |
/errors/auth/not-found | 404 | The thing you named does not exist, or is not yours to see. detail says what kind of thing. | |
/errors/auth/bad-request | 400 | A value was not acceptable, such as a malformed email address. detail says which. | |
/errors/auth/bad-url | 400 | The URL asked for an organization is not one it may go by: not lowercase letters and digits in words joined by single hyphens, longer than 48 characters, a word the console's own pages use, or a word no URL may hold. detail says which, without repeating a word no URL may hold. A URL another organization holds is a 409 instead. | |
/errors/auth/conflict | 409 | It already exists, conflicts with something that does, or something is not in the state the request needs, such as deleting your account while you own an organization other people are in. detail says what. | |
/errors/auth/sso-required | 403 | Your address's domain signs in through the deployment's identity provider alone, so the email-and-password form refuses it: sign-in, sign-up and a password reset. The sign-in page offers the provider's button instead (Configuration). | |
/errors/auth/sign-up-closed | 403 | A new person was turned away because the deployment lets new people in by invitation (AUTH_DISABLE_SIGNUP, on by default), at the email-and-password form or through its identity provider. An address an invitation is waiting for still gets in. After a provider's sign-in, the console shows a page saying so. | |
/errors/authz/forbidden | 403 | You are signed in and this is not allowed. detail says why. | |
/errors/authz/insufficient-role | 403 | Your role does not allow this. detail names the least role that would, such as required admin, have member. | |
/errors/tenant/cross-tenant-denied | 403 | Reserved for a request that reaches outside the organization or project it may act in; no lane returns it. | |
/errors/bad-request | 400 | The request body or query string is not the shape the lane takes, or a value failed its rule. detail names the shape or the parameter, never the value sent. | |
/errors/payload-too-large | 413 | The request body is larger than this route accepts, such as a body over 8 KiB sent to the CLI's lanes. | |
/errors/not-found | 404 | No lane answers at this path on the machine host, under /v1, /cli or /otlp. Not a resource a lane looked for: that is /errors/auth/not-found. Under /otlp the body is OTLP's Status rather than a problem document, its message opening with the type. | |
/errors/method-not-allowed | 405 | The lane does not take this method. The Allow header lists the ones it does. On /otlp/v1/traces the body is OTLP's Status. | |
/errors/incompatible-client | 426 | Reserved for a client older than the oldest version Telmoni supports; no lane checks a client's version, so none returns it. | |
/errors/tenant/rate-limited | 429 | Too many requests. Wait and try again. A Retry-After header carries the same number of seconds. On the hosted service the same type answers the ceiling of the organization's plan on its data out for the UTC day — the read API's answers and the exports — until midnight UTC; detail says so. | retry_after_secs |
/errors/tenant/feature-off | 503 | This feature is switched off, for your organization or for the whole deployment. detail says which in a sentence. | flag, retry_after_secs |
/errors/mail/delivery-failed | 502 | An email this request depended on, such as a confirmation code, could not be sent. | |
/errors/connectors/key-unavailable | 502 | The key that seals connector secrets could not be reached, so a connector could not be set up or its secret rotated. Nothing was changed; try again shortly. | |
/errors/internal/database | 500 | Telmoni's database failed. | |
/errors/internal/unknown | 500 | Something else on Telmoni's side failed. | |
/errors/agent/disabled | 503 | The operator of this deployment has not configured the console agent. | |
/errors/agent/model-unavailable | 502 | The model or embeddings service behind the console agent did not answer. Nothing was changed; try again shortly. | |
/errors/agent/rate-limited | 429 | You have asked the console agent as many questions as this hour allows. | retry_after_secs |
/errors/telemetry/invalid-batch | 400 | An export to /otlp/v1/traces did not decode as OTLP in the encoding its Content-Type named, held no span, held more than 1,000, did not arrive within 60 seconds, or could not be read. On that lane the body is OTLP's Status rather than a problem document, its message opening with the type. | |
/errors/telemetry/batch-too-large | 413 | An export was larger than 1 MiB once decompressed. Send fewer spans per export. | max_bytes |
/errors/telemetry/store-unavailable | 503 | The store that keeps spans, or the key service that seals a project's hashing key, did not answer; or a project's first export came while the project was being moved to another organization or deleted. Nothing was kept; retry after the second Retry-After gives. | retry_after_secs |
/errors/plan/limit-reached | 402 | What was asked is past what the organization's plan holds. Only a deployment that sells plans answers it, never a self-hosted one: on the hosted service, a paused organization's exports, agent questions, invitations and members added to a project from it, an invitation past Hobby's one member and the seat it would take, a second organization asked for while the person's Hobby place is held, which is paid for first instead, a cancellation of an organization that could not fall to Hobby, and an organization offered to someone whose free plan is already taken (Billing). detail says what lifts it; on /otlp/v1/traces it is OTLP's Status, its message opening with the type, and an exporter drops the export rather than retrying it. | entitlement |
feature-off answers 503 with a retry hint, not 404, on purpose: the route
exists and the switch is Telmoni's, so a program should wait and retry rather
than conclude the route is gone.
Methods, and lanes that do not exist
Every lane under /v1 and /cli answers a problem document, the two
the door itself mints among them; ingest, under /otlp, answers OTLP's Status
instead, these two among them (Sending spans).
A method a lane does not take is 405 with an Allow header,
/errors/method-not-allowed. The API takes GET and
HEAD, and OPTIONS alone answers 204 with Allow: GET, HEAD, OPTIONS; the
CLI's lanes and ingest take POST, and every other method, OPTIONS
included, is told so:
{
"type": "/errors/method-not-allowed",
"title": "method not allowed",
"status": 405,
"detail": "this lane takes POST"
}A path no lane serves, under /v1, /cli or /otlp, is 404 with
/errors/not-found: a type apart from /errors/auth/not-found, which a lane
answers about a resource it looked for and did not find, so a client can tell
a missing lane from a missing row:
{
"type": "/errors/not-found",
"title": "not found",
"status": 404,
"detail": "no such lane"
}On /v1, a server that cannot reach its database while it checks the key
answers 503 with /errors/auth/identity-unavailable, from the table; anywhere
else a database failure is 500 with /errors/internal/database.