Handle errors
Read dispatch errors and workflow failures, then decide what can be retried.
Understand failure results
Section titled “Understand failure results”The error you receive depends on the operation. A dispatch rejects its promise when the agent fails; a workflow normally returns a result containing its failed tasks. Use the table below to choose how to handle each call.
| Call | On failure |
|---|---|
dispatch(), sandbox.dispatch() | Rejects with an OutpostError. |
createSandbox() | Rejects with an OutpostError. |
sandbox.command() | Resolves with status, even non-zero. Rejects when stopped: code timeout after deadlineMs, aborted when the sandbox closes. |
defineCommandTask() | Fails its task with code process on a non-zero exit. |
workflow.start() | Resolves with status and errors, also when you cancel it ("cancelled"). result.unwrap() throws a WorkflowFailure unless status is "done". |
steering.send() | Rejects with code steering when the instruction is not delivered. |
dispatch() or sandbox.command() cancelled with your own signal | Rejects with the signal’s reason, as passed to abort(), not an OutpostError. |
Read an OutpostError
Section titled “Read an OutpostError”Catch an OutpostError to read its code, message and recovery information. Keep other errors visible by throwing them again; recovery details help locate work retained after a failed dispatch.
API reference: OutpostError.
Use the recovery information to find work that was preserved after a failure.
API reference: recoveryDetails.
Recover work shows how to use these locations.
Fault codes
Section titled “Fault codes”API reference: FaultCode.
Recognize quotas and outages
Section titled “Recognize quotas and outages”quotaFault(error) and unavailableFault(error) search the error and up to seven wrapped causes. Each returns undefined when the failure is something else.
An outage keeps its process, provider or timeout code. Use unavailableFault() to recognize it, not the code. Quota pauses explains which signals count as a quota.
A connection timeout keeps the code timeout. When a CLI agent last reported a connection failure, details.agentDiagnostic is "connection" and unavailableFault() treats it as an outage. Diagnostics shows how to check the endpoint.
Handle a failed workflow
Section titled “Handle a failed workflow”A failing task does not make start() reject. Read status and errors, or call unwrap() to throw.
WorkflowFailure.cause is the first entry of errors, so quotaFault() and unavailableFault() work on it directly. unwrap() also throws for "paused", "waiting-input" and "cancelled" runs.
API reference: WorkflowFailure, WorkflowBudgetExceeded, WorkflowUsageUnavailable, LoopTaskExhausted, ResponseError, ReplayDivergence and TransportConflict.
Retry deliberately
Section titled “Retry deliberately”A task retries only when it has a retry policy; accepts chooses which errors qualify; without it, every failure is retried. Retry outages and timeouts; do not retry configuration, prompt or conflict.
A retry runs the whole task again and can repeat its effects. Concurrency, retries and timeouts covers the options and Retry-After.
Log safely
Section titled “Log safely”Log code, message and recoveryDetails(error). Do not dump details or the whole error: a failed process carries the agent’s stdout and stderr, and ResponseError.raw holds its answer. Both can contain repository content or secrets the agent printed.
For the full record of a failed dispatch, open its journal from the logReference recovery field.
Limits
Section titled “Limits”- Some failures are plain
Errors: invalid task or workflow definitions, and a checkpoint already owned by another runner. - A
timeoutdoes not prove that external effects were rolled back. Check the retained branch before running again.
API: OutpostError · FaultCode · recoveryDetails · quotaFault · unavailableFault · WorkflowFailure · WorkflowResult · ResponseError · TransportConflict