Error Codes
Every execution-surface error the router emits, with HTTP status, retry semantics, and the operator action that resolves it. Key on error.code, it is stable across releases. The error.type field still diverges from the OpenAI vocabulary on some routes, do not switch on it.
Overview
Every response carries an X-Request-ID header. Include
that value when filing a support ticket, it is the primary
correlation key into the router logs.
Error Format
{
"error": {
"message": "Tool 'github.create_repo' is not registered with any online XEM",
"type": "invalid_request_error",
"code": "exec_tool_not_found",
"param": null
}
}
The envelope shape is {message, type, code, param}.
On 429 responses the rate-limit middleware injects two additional
fields inside error: retry_after (int,
seconds) and retry_strategy (object with
type, initial_delay_ms,
max_delay_ms, multiplier,
jitter). These are vendor extensions; the standard
Retry-After response header is also set.
Exec Invocations
Codes emitted by the /v1/exec/invocations family of
routes when starting, listing, reading, or cancelling a tool
invocation.
| Code | HTTP | Retryable | Description | Operator Action |
|---|---|---|---|---|
invalid_body |
400 | No | Request body failed JSON decoding or schema validation. | Verify the request matches the documented schema. The
message field names the failing field
when available. |
exec_tool_not_found |
400 / 404 | No | Tool name is not present in any online XEM manifest. Returned as 404 by the tools-catalog read route and as 400 when supplied as the invocation target. | Verify the tool name. List visible tools via the tools-catalog endpoint and check that an XEM advertising the tool is currently online. |
tool_not_mcp_visible |
400 | No | Tool exists but is not exposed through the MCP-visible surface the caller is using. | Use the MCP-visible alias or call through the route that matches the tool's visibility class. |
tool_executor_unavailable |
503 | Yes | No XEM agent is currently online to execute this tool (emitted from the chat-completions tool-bridge path). | Confirm at least one XEM advertising the tool is enrolled and reachable; retry after the agent reconnects. |
invocation_not_found |
404 | No | No invocation matches the supplied id within the caller's project scope. | Verify the invocation id. Cross-project reads return this code rather than 403 to avoid leaking existence. |
invocation_terminal |
409 | No | Cancel or mutation attempted against an invocation that has already reached a terminal state (completed, failed, or cancelled). | No action required. Read the invocation to see its final status. |
unavailable |
503 | Yes | A backing dependency (queue, scheduler, or executor) is temporarily unable to accept the request. | Retry with exponential backoff. Persistent failures indicate an infrastructure incident. |
cancelled |
499 | No | Invocation was cancelled before completion. On
streaming responses this code also appears mid-stream
inside the SSE error payload (no type
field is set in that case). |
None. The client requested cancellation. |
exec_idempotency_conflict |
409 | No | The supplied Idempotency-Key matches a
prior request with a different body. |
Use a fresh idempotency key, or reissue the original request body. |
Exec Approvals
Codes emitted by the /v1/exec/approvals routes that
accept or reject pending human-in-the-loop approvals.
| Code | HTTP | Retryable | Description | Operator Action |
|---|---|---|---|---|
approval_not_found |
404 | No | No approval record matches the supplied id within the caller's project scope. | Verify the approval id. The record may have been garbage-collected after the invocation reached a terminal state. |
approval_not_pending |
409 | No | The approval record exists but has already been accepted, rejected, or expired. | Read the approval record to see the final decision and decided-by user. |
Exec Context
Codes emitted by the workspace and context lookup paths that back the execution surface (workspace resolution, retriever fetch, artifact reads).
| Code | HTTP | Retryable | Description | Operator Action |
|---|---|---|---|---|
missing_workspace_id |
400 | No | Request omitted the required workspace identifier. | Supply workspace_id in the request body
or path. |
invalid_workspace_id |
400 | No | The workspace identifier is not in the expected
external ws_ hex form. |
Use the operator-facing ws_<hex>
form. UUIDs are not accepted on operator surfaces. |
workspace_not_found |
404 | No | No workspace matches the supplied id within the caller's project. | Verify the workspace exists and the API key has access to its owning project. |
workspace_lookup_failed |
500 | Yes | Workspace resolution failed for a transient reason (database or cache fault). | Retry with backoff. Persistent failures indicate a database incident. |
project_mismatch |
403 | No | The supplied workspace, chat, or artifact belongs to a project other than the one the API key is scoped to. | Use an API key issued in the resource's owning project. |
authentication_required |
401 | No | Route requires a caller identity but the request presented none. | Attach a valid Authorization: Bearer
header. |
retriever_failed |
502 | Yes | The retrieval backend serving the workspace returned an error. | Check retriever health. Retry after the backend recovers. |
payload_too_large |
413 | No | Request body exceeded the configured size limit. | Reduce the payload, or stream the input in chunks if the route supports it. |
model_capability_missing |
400 | No | The model bound to the workspace does not advertise
a capability the request requires (typically
tool_calling for execution-enabled
requests). |
Switch to a model that advertises the required
capability. Use
GET /v1/models?capability=tool_calling
to list candidates. |
Scope & Auth Errors
| Code | HTTP | Retryable | Description | Operator Action |
|---|---|---|---|---|
scope_insufficient |
403 | No | API key is missing the scope required for the route
(for execution routes the required scope is
execution; an inference-only key cannot
use x_exec: true). |
Issue or rotate an API key that includes the
required scope. Note: this response currently carries
type: authentication_error on a 403,
which diverges from the OpenAI vocabulary; switch on
code, not type. |
cross_project_access |
403 | No | API key tried to read or mutate a resource in a different project. | Use a key issued in the target project. |
Quota & Rate Limit
Execution routes flow through the same credit-gate and rate-limit middlewares as inference; the codes below are the ones operators integrating against the execution surface will see.
| Code | HTTP | Retryable | Description | Operator Action |
|---|---|---|---|---|
insufficient_quota |
402 | After top-up | Project has no remaining credit. The envelope
currently carries type: insufficient_quota
rather than the spec insufficient_quota_error;
switch on code. |
Top up the project's billing balance. |
billing_delinquent |
402 | No | Project has an unpaid balance and is in dunning state. | Resolve the outstanding invoice in the billing dashboard. |
rate_limit_exceeded |
429 | Yes | Per-key or per-tier request rate cap was exceeded.
Response carries Retry-After as both a
header and as error.retry_after inside
the envelope; error.retry_strategy
describes the recommended backoff curve. |
Honour Retry-After. Persistent
throttling indicates the key needs a higher tier. |
capacity_exceeded |
429 | Yes | Downstream inference capacity is saturated. | Retry with backoff. |
endpoint_restricted |
403 | No | API key is not entitled to use the targeted endpoint. | Use an endpoint the key is entitled to, or update the key's entitlements. |
Lifecycle Errors
Codes emitted by management routes that mutate long-lived execution state (maintenance, cancellation).
| Code | HTTP | Retryable | Description | Operator Action |
|---|---|---|---|---|
already_terminal |
400 | No | Maintenance route was asked to transition a record that has already reached a terminal state. | None. Read the record to see its final status. For
the invocation-cancel route the equivalent condition
returns invocation_terminal at HTTP 409
(see Exec Invocations). |
invalid_state |
409 | No | Requested transition is not legal from the record's current state. | Read the record's current state and choose a valid transition. |
Enrollment Protocol Errors
The codes in this section are not HTTP error
envelopes. They are delivered out-of-band over the XEM
enrollment ZMQ/CURVE socket inside the
EnrollmentResponse protocol message and are surfaced
by the XEM client (e.g. xeroctl agents enroll),
never by an HTTP client. There is no associated HTTP status code.
| Code | Retryable | Description | Operator Action |
|---|---|---|---|
exec_manifest_invalid |
No | The XEM's capability manifest failed schema validation during enrollment. | Review the manifest against the documented schema. Check for missing required fields (workspace entries, tool declarations). Re-validate the manifest before re-enrolling. |
agent_name_in_use |
No | A join key attempted to reserve a
registration_name already in use by a
live agent. |
Either pick a different registration name, or rotate the join key with replace-semantics to retire the existing agent. |
agent_name_conflict |
No | Two agents came online with the same
registration_name but different CURVE
keys; the protocol entered the conflict-pill state. |
Investigate why two agents share the same name -- typically a misconfigured replacement or a stale join key. Resolve via the management surface, then re-enroll. |