How-to guide

Handle errors and retries

Retry failed activities, route failures to a handler with onError, and log errors with the error.* fields.

Flow Current 2 min read Updated

Prerequisites

  • A basic workflow ([Build a workflow](build-a-workflow.md))

Per-activity handling#

Every activity can declare an onError block:

json
"onError": {
  "strategy": "fail",
  "retries": 2,
  "retryDelaySeconds": 5,
  "activityId": "a_handler"
}
Field Meaning
strategy fail stops the run, continue carries on to the next activity, goto jumps to the activity named in activityId
retries How many times to retry before applying the strategy
retryDelaySeconds Wait between retries
activityId The handler to jump to. Required when the strategy is goto

Workflow-level handler#

A workflow can declare a catch-all for anything not handled at activity level:

json
"onError": { "strategy": "goto", "activityId": "a_global_error_handler" }

Logging the failure#

After an onError jump, the target chain can read error.* fields. The canonical first step of an error chain is a log activity that templates them:

json
{
  "id": "a_global_error_handler",
  "type": "log",
  "inputs": [
    { "name": "level",   "value": "error" },
    { "name": "message", "value": "{{error.activityId}} failed: {{error.errorMessage}}" }
  ],
  "next": "a_notify_ops"
}

log writes a real entry to the run's execution log; it is not a notification. Follow it with a messaging or email activity if people should be alerted.

Sub-workflow failures#

When a sub-workflow fails, the parent workflow handles it explicitly through the onError block on the sub_workflow activity.

Long-running work#

Execution state is persisted, so a network interruption does not lose a run. Use delay, approval and external_task for waits that last hours or days rather than holding work open in a script.

Expected result

  • Transient failures are retried, and permanent failures reach an explicit handler