Compute
Compute error vocabulary
Every refusal Lithi Compute can return, what each one means, whether retrying helps, and how to read a field-level validation failure.
On this page
On this page
How refusals are shaped
Every refusal carries a stable code and a p_next_action telling you what to do. Read the code to decide whether to retry; read the next action to decide what to change.
Two things are deliberately absent from a refusal: your submitted values, and any internal detail about why a downstream system was unavailable. A refusal names the field, never the content of the field.
The codes
Correct your request — retrying unchanged will not help:
INVALID_REQUEST— the body failed validation. See Reading a validation failure below.UNSUPPORTED_SEMANTICS— the request is well-formed but asks for a combination that is not permitted.DATA_PROFILE_REQUIRED— the operation needs a data profile you did not declare.CREDENTIAL_DETECTED— something in your request looked like a secret. Remove it. This is a refusal to store, not an accusation.CONTEXT_OVERFLOW— your declared input exceeds what the capability accepts.PAYLOAD_TOO_LARGE— the body exceeded the 64 KiB ceiling.UNSUPPORTED_MEDIA_TYPE— sendapplication/json.NOT_ACCEPTABLE— yourAcceptheader does not permit a response this endpoint can produce.
Fix your credentials or permissions:
UNAUTHENTICATED— no valid API key. Check theAuthorization: Bearerheader.FORBIDDEN— the key is valid but lacks the scope this operation requires, or the request referenced an account that is not yours.
Retrying may help:
RATE_LIMITED— slow down. HonourRetry-Afterif present.UNAVAILABLE— the operation is not currently served. Today this is the expected answer for creating a quote, creating a job batch, listing capabilities, and preparing or completing an input file.INTERNAL_ERROR— an unexpected fault. Retry once; if it persists, it is ours, not yours.
Neither:
NOT_FOUND— the record does not exist, or is not visible to your account. These are deliberately the same answer.CONFLICT— an idempotency collision: the same key was reused with a different body.
Reading a validation failure
A malformed request does not just tell you it was malformed. It names the fields.
Over MCP, a bad argument comes back as a tool execution error — a normal result with isError: true — rather than a protocol error, so that a model can read it and correct itself. The structured content looks like this:
{
"code": "ARGUMENTS_INVALID",
"tool": "lithi.run",
"issue_count": 2,
"issues": [
{ "path": "input.public_bounds.files", "code": "too_big", "expected": "Too big: expected number to be <=1000000" },
{ "path": "contract.output_schema_id", "code": "invalid_type", "expected": "Invalid input: expected string, received undefined" }
],
"p_next_action": "Correct the listed argument paths and call lithi.run again; the full input schema is published by tools/list."
}
Three things worth knowing about that payload:
pathis the dotted location of the failing field, so you can correct it directly.expecteddescribes what the schema wanted. It never contains what you sent — an argument can carry a credential, and this text is handed to a language model.- At most twelve issues are listed, but
issue_countis the true total. If it exceeds twelve, fix the listed ones and resubmit to see the rest.
An unknown tool name is different: that comes back as a JSON-RPC protocol error, because it is not something a corrected argument can fix.
Why a refusal is not a failure
Compute refuses rather than guesses. A request that is ambiguous, over a limit, or missing authority is rejected while it is still cheap, before anything is priced or executed. A refusal at submission costs you nothing.
Related
- Submit work — the contract a request must satisfy
- MCP tools — how these refusals reach an AI agent