Skip to main content
A failed run throws or returns an error from the run or continue call. A pause (waiting_for_human) or a stop condition (stopped) is not an error: both return a normal result. Which failures also send a run.failed event differs by language, so don’t rely on the event alone to detect a failure.

How a failed run surfaces

Which events fire when something fails

Lifecycle hooks lists every event.

Find the cause of an error

TypeScript error types

AgentGatewayError has status, statusText, headers, body, requestId, generationId, reason, errorType, errorOrigin, failedProviders, failedStatuses and routing diagnostics. Failed runs and steps keep the same details in errorDetails. A failure partway through a streamed response is an AgentStreamError, a subclass with code and retryable. AgentSchemaValidationError has a target of tool_input, tool_output, tool_event or agent_output, and details with the validator’s error. Treat these as contract failures, not transient model failures. To classify any error, for example in modelRetry.retryOn, use agentErrorIsRetryable(error), agentRetryAfterMs(error) and agentErrorIsContextOverflow(error).

Rust error type

Every runtime failure is an AgentError; read it with message(). Gateway PhaseoError values are converted into AgentError, so if you need the original gateway status and body, call the phaseo client directly or implement a custom ModelClient that keeps them.

Recover from tool errors

By default a tool error fails the run. Set the tool’s error policy to return-to-model when the model can sensibly try something else: the error becomes the tool result {"error": "..."} and the run continues. Keep the default, fail-run, for unsafe or unrecoverable failures.

Handle cancellation and timeouts

A tool timeout or cancellation doesn’t always stop the tool’s own work. Give HTTP, database and process calls inside tools their own deadlines, and treat a cancelled or timed-out run as finished unless your application starts a new one.

Recover from an interrupted TypeScript run

If a run crashed or was cancelled mid-step, its history can hold tool calls without results, which providers reject. TypeScript’s continueRun() answers them as not run and sends history.repaired. Call repairToolHistory(messages) yourself if you reuse the messages elsewhere.

Check these first

  • PHASEO_API_KEY reaches the process and is passed to the gateway client.
  • Every tool has a unique, stable ID.
  • Approvals, rejections and tool outputs use exact tool-call IDs, and a human input message is never a substitute for a tool output.
  • The whole run result is saved before you show an approval UI or hand control to another request or worker.
  • Validators are deterministic and free of side effects, so a failed check can be retried safely.
  • Model retries are bounded; validation and approval failures shouldn’t be retried blindly.
To see which step failed, record step.started, model.requested and tool.failed with lifecycle hooks, and see Observability for the IDs that tie a step to gateway logs.
Last modified on November 5, 2026