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 immediatelycontinue-workflow: Proceeds to next steps (useful after error recovery)retry-step: Re-queues the current step (requiresmaxRetriesin error handling)retry-workflow: Clears queue and restarts from entrypoint (requiresmaxRetriesin 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
TimeoutErroris raised - The timeout error is handled using the step's
onErrorconfiguration - If no
onErroris 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-filequeued - Iteration 2 (file3): succeeds → queues
process-file - Result:
process-fileruns twice (for file1 and file3)