Skip to content

Error codes

This page: every failure the model can read back, and what it should do about it. Failures are typed results, not exceptions — a tool call that fails still returns a tool result, so the model can self-correct instead of guessing.

Every model-visible tool result in the generated app has the same envelope:

ts
{ ok: boolean, value: unknown }   // on failure, value is { error: { code, message, retry, details? } }

retry is the actionable part: no · yes · after-refresh · after-delay · with-confirmation · with-changes.

Capability errors (presentation plane)

The closed enum from @agent-surface/core. These reach the model for view:* capabilities and for contextual domain references.

CodeMeansThe model should
CAPABILITY_NOT_FOUNDNot on the current surfaceRe-read the catalog; the page changed
CAPABILITY_NOT_AVAILABLEPresent, but not callable now — reason says whyDo the enabling step first (“Select at least one draft invoice”)
AMBIGUOUS_INSTANCESeveral mounted instances matchName the instance
COMPONENT_UNMOUNTEDThe owner left the pageRe-read the surface
STALE_CAPABILITYThe registration is from a previous mountRe-read the surface
INVOCATION_CONFLICTAnother invocation of the same capability is in flightWait, then retry
INVALID_INPUTSchema or precondition rejected the input. details.lockedFields means a bound key was suppliedFix the input — and never try to override a bound field
NOT_AUTHENTICATED / NOT_AUTHORIZEDIdentity is missing or insufficientStop; this is not a retryable condition
PRECONDITION_FAILEDSemantically invalid against current stateRead state, then retry with changes
CONFIRMATION_REQUIREDThe call needs human approvalRequest it — it is not skippable
CONFIRMATION_INVALIDreason: denied | expired | consumed | mismatchdenied → stop and report honestly. mismatch → state changed after approval; start over
RATE_LIMITEDToo many callsBack off
TIMEOUT / CANCELLEDThe invocation did not completeRetry only if idempotent
EXECUTION_FAILEDThe handler threwReport; do not loop

CONFIRMATION_INVALID { reason: "mismatch" } is the bait-and-switch guard: approval is bound to the exact effective input, so changing the selection after a human approves invalidates the evidence rather than executing something else.

Domain errors (authoritative plane)

From @orpc-agent/core, produced by the governed pipeline around your procedure:

CodeStage
CAPABILITY_NOT_FOUNDNot exposed on this surface, or hidden by policy — deliberately indistinguishable from nonexistent
INPUT_INVALIDValidation, before your handler runs
UNAUTHENTICATED · FORBIDDENAuthentication and authorization
POLICY_DENIED · POLICY_FAILEDA policy denied, threw, or timed out — failure is closed
APPROVAL_*Server approvals: REQUIRED, PENDING, REJECTED, EXPIRED, CONSUMED, INPUT_MISMATCH, SELF_APPROVAL, UNSERIALIZABLE_INPUT. The template gates issue-invoice and delete-invoice this way; the coordinator is configured in server/runtime.ts
EXECUTION_FAILEDYour handler threw a non-typed error
OUTPUT_INVALIDThe handler returned something the output schema rejects
TIMEOUT · CANCELLEDExecution did not complete
AUDIT_UNAVAILABLE · ADAPTER_ERRORInfrastructure
INTERNAL_ERRORAnything else — deliberately opaque

Your own typed procedure errors (.errors({ INVOICE_NOT_FOUND: … })) pass through with their public message. Everything else the model sees is either a public code/message or a generic INTERNAL_ERROR: stack traces and internals never reach it.

Host errors (transport)

PROTOCOL_VERSION_MISMATCH · PROTOCOL_DECODE_ERROR · CATALOG_COLLISION · MODEL_NOT_CONFIGURED · MODEL_TIMEOUT · MODEL_ERROR · RUN_LIMIT_EXCEEDED · TRANSPORT_FAILED — see Host protocol.

Two host-produced tool results are worth knowing:

CodeMeans
CAPABILITY_NOT_FOUNDThe model called a wire name that is not on the live surface (retry: "after-refresh")
TOOL_NOT_EXECUTEDA tool call Mastra left open could not be answered — the model is told so explicitly (retry: "yes") rather than receiving silence

Reading them in the app

The tool pills in the copilot render the same payloads the model receives, so if you can read the card you can read the transcript the model reasoned over. The host guarantees the pairing behind them: every tool-call frame gets a tool-result, including the ones the runtime dropped (ADR-0009).

Testing them

Assert the code and the retry hint — they are API. capabilities/governance.test.ts and app/features/invoices/capabilities.test.tsx cover hiding, unavailability, locked fields and the approve/reject paths without a model; see Testing without an LLM.

Built on Agent Surface, oRPC Agent, Mastra and assistant-ui.