Skip to main content

Error Handling

Error Strategies

Define how steps should handle errors:

1. Stop Workflow (Default)

{
"onError": {
"action": "stop-workflow"
}
}

2. Continue Workflow

Skip the failed step and continue:

{
"onError": {
"action": "continue-workflow"
}
}

3. Retry Step

Retry the failed step with limits:

{
"onError": {
"action": "retry-step",
"maxRetries": 3
}
}

4. Retry Workflow

Restart the entire workflow:

{
"onError": {
"action": "retry-workflow",
"maxRetries": 2
}
}

Using in Conditions

{
"id": "validate-critical-data",
"action": "template::validate",
"parameters": {
"data": "{{user.input}}"
},
"condition": {
"if": "{{validate-critical-data.output.valid}} == false",
"then": "stop-workflow",
"else": "process-data"
}
}

Mixing with Steps

{
"condition": {
"if": "{{error.critical}} == true",
"then": ["send-alert", "stop-workflow"],
"else": ["log-warning", "continue-processing"]
}
}

in Error Handling

The following will stop the workflow if the 'important-operation' step has failed 3 times.

{
"id": "important-operation",
"action": "template::external_api",
"onError": {
"action": "stop-workflow",
"maxRetries": 3
},
"next": "next-step-id"
}

Workflow Control Behavior

  • stop-workflow: Clears the execution queue, workflow ends immediately
  • continue-workflow: Proceeds to next steps (useful after error recovery)
  • retry-step: Re-queues the current step (requires maxRetries in error handling)
  • retry-workflow: Clears queue and restarts from entrypoint (requires maxRetries in error handling)

Important: When used in step arrays, stop-workflow and retry-workflow will prevent subsequent steps in the same array from executing.

Timeout Configuration

Configure step-level timeouts to prevent steps from running indefinitely:

Basic Timeout

{
"id": "api-call-with-timeout",
"action": "example::api_call",
"timeout": 30, // 30 seconds
"parameters": {
"url": "{{api.base_url}}/slow-endpoint"
},
"onError": {
"action": "retry-step",
"maxRetries": 2
}
}

Timeout with Different Error Strategies

{
"id": "critical-operation",
"action": "example::database_query",
"timeout": 60,
"onError": {
"action": "stop-workflow"
}
},
{
"id": "optional-operation",
"action": "example::cache_update",
"timeout": 10,
"onError": {
"action": "continue-workflow"
}
}

Timeout Behavior:

  • When a step exceeds its timeout, a TimeoutError is raised
  • The timeout error is handled using the step's onError configuration
  • If no onError is specified, the workflow stops (default behavior)
  • Timeout values are specified in seconds as integers or floats

Important: runLimit and Retry Conflicts

When using timeout with onError.action: "retry-step", ensure your runLimit allows for retries:

{
"id": "api-call-with-retries",
"action": "example::api_call",
"timeout": 30,
"runLimit": 3,
"onError": {
"action": "retry-step",
"maxRetries": 2
}
}

Conflict Example (Will Not Retry):

{
"id": "problematic-step",
"timeout": 10,
"runLimit": 1,
"onError": {
"action": "retry-step",
"maxRetries": 3
}
}

Why: The step will timeout and attempt to retry, but runLimit: 1 prevents any retries from executing. The retry mechanism will report "has reached its run limit" and stop.

Best Practice: Set runLimit to maxRetries + 1 to allow all retry attempts, or use runLimit: -1 for infinite retries.

Error Handling in Loop Iterations

When using error handling with loop iterations, retries are tracked per iteration:

{
"id": "loop-files",
"action": "logic::loop",
"parameters": {
"items": ["file1", "file2", "file3"]
},
"next": ["download-file"]
},
{
"id": "download-file",
"action": "addon::download",
"onError": {
"action": "retry-step",
"maxRetries": 3
},
"next": ["process-file"]
}

Behavior:

  • Each iteration has its own independent retry counter
  • If iteration 1 (file2) fails after 3 retries, it stops and does not queue process-file
  • Iterations 0 and 2 (file1 and file3) continue normally if successful
  • The next step (process-file) only executes for successful iterations
  • This prevents one failed item from blocking the entire workflow

Example Execution:

  • Iteration 0 (file1): succeeds → queues process-file
  • Iteration 1 (file2): fails 3 times → stops, no process-file queued
  • Iteration 2 (file3): succeeds → queues process-file
  • Result: process-file runs twice (for file1 and file3)