Configure Retry Strategies for Transient Task Failures
For the complete documentation index, see llms.txt. For a full content snapshot, see llms-full.txt. Append.mdto anykestra.io/docs/*URL for plain Markdown.
Retries automatically rerun failed tasks. Each retry creates a new task run attempt based on the retry configuration defined in the flow.
Task-level retries
Example
This task runs up to 5 times total (1 initial attempt + up to 4 retries) with a 15-minute interval between attempts:
- id: retry_sample type: io.kestra.plugin.core.log.Log message: my output for task {{ task.id }} timeout: PT10M retry: type: constant maxAttempts: 5 interval: PT15MConstant retry, 4 attempts, 0.25-second interval — uses {{ taskrun.attemptsCount }} to conditionally exit:
id: retrynamespace: company.teamdescription: This flow retries 4 times and succeeds on the 5th attempt
tasks:- id: failed type: io.kestra.plugin.scripts.shell.Commands taskRunner: type: io.kestra.plugin.core.runner.Process commands: - 'if [ "{{ taskrun.attemptsCount }}" -eq 4 ]; then exit 0; else exit 1; fi' retry: type: constant interval: PT0.25S maxAttempts: 5 maxDuration: PT1M warningOnRetry: true
errors: - id: never_happen type: io.kestra.plugin.core.log.Log message: "Never happened {{ task.id }}"Timeout vs. Max Retry Duration
timeout: Maximum duration for a single task attempt (initial or retry). If exceeded, the attempt fails.retry.maxDuration: Maximum total time allowed for the task, including all attempts and delays. Once exceeded, retries stop.
Example: With timeout: 10m and maxDuration: 30m:
- Each attempt can last up to 10 minutes.
- The overall retries stop after 30 minutes in total.
Ensure retry.interval is smaller than maxDuration, or retries may never run.
Retry options
| Name | Type | Description |
|---|---|---|
type | string | Retry strategy: constant, exponential, or random. |
maxAttempts | integer | Maximum number of attempts, including the initial run. maxAttempts: 1 means no retry; maxAttempts: 2 means one retry after the initial attempt. |
maxDuration | Duration | Maximum total time for the task, across all attempts. |
warningOnRetry | Boolean | Marks execution as WARNING if retries occurred (default: false). |
behavior | string | What to retry when set on a flowable task. RETRY_FAILED_TASK (default) retries only the failed child task. RETRY_FLOWABLE reruns the entire flowable block from the start. See Retry on flowable tasks. |
Duration format
Durations use ISO 8601 format (weeks, months, years not supported). Examples:
| Value | Description |
|---|---|
| PT0.25S | 250 ms |
| PT2S | 2 seconds |
| PT1M | 1 minute |
| PT3.5H | 3 hours, 30 minutes |
| P6DT4H | 6 days, 4 hours |
Retry on flowable tasks
Flowable tasks such as Sequential and Parallel accept a retry block with a behavior property that controls what is retried when a child task fails.
Default behavior: RETRY_FAILED_TASK
By default (behavior: RETRY_FAILED_TASK), a retry on a flowable task does not rerun the group. It sets the default retry policy that child tasks inherit when they have no retry of their own. Only the failed child is retried; earlier tasks do not run again.
id: token_and_apinamespace: company.team
tasks: - id: group type: io.kestra.plugin.core.flow.Sequential retry: type: constant maxAttempts: 2 interval: PT1S tasks: - id: get_token type: io.kestra.plugin.core.output.OutputValues values: result: "{{ now() }}" - id: call_api type: io.kestra.plugin.core.execution.Fail errorMessage: "Token expired"If call_api fails, Kestra retries only call_api. get_token does not run again, and each retry of call_api uses the same token from the first run. A token that expires between the two tasks is never refreshed this way.
Rerun the whole block: RETRY_FLOWABLE
Set behavior: RETRY_FLOWABLE to rerun the entire flowable block from the start when any child task fails. All child task runs from the previous attempt are discarded and the group begins again.
id: token_and_apinamespace: company.team
tasks: - id: group type: io.kestra.plugin.core.flow.Sequential retry: type: constant maxAttempts: 3 interval: PT1S behavior: RETRY_FLOWABLE tasks: - id: get_token type: io.kestra.plugin.core.output.OutputValues values: result: "{{ now() }}" - id: call_api type: io.kestra.plugin.core.execution.Fail errorMessage: "Calling API with {{ outputs.get_token.values.result }}"When call_api fails, get_token runs again on the next attempt, producing a fresh token.
Behavior by flowable type:
Sequential,Parallel,WorkingDirectory,AllowFailure,If,Switch,Dag— all child tasks rerun from the start on each attempt.IfandSwitchre-evaluate their condition or value, so a retry can take a different branch.Loop— only the failed iteration restarts from its first child task. Other iterations are not touched.AllowFailureand tasks withallowFailure: true— failure is allowed only after the last attempt has been exhausted.
RETRY_FLOWABLE is rejected on runnable (non-flowable) tasks and at flow level.
Retry a group as a new execution
To retry a set of tasks as a completely new child execution, use a Subflow with retry. Each retry creates a new execution, so all tasks in the subflow run again from the start with a separate execution ID.
id: parentnamespace: company.team
tasks: - id: group type: io.kestra.plugin.core.flow.Subflow namespace: company.team flowId: get_token_and_call_api retry: type: constant maxAttempts: 2 interval: PT1SToken refresh pattern
For the specific case of a short-lived token that may expire between tasks, Credentials (Enterprise Edition and Cloud) is the cleaner solution. Kestra fetches and refreshes the token automatically, so every retry gets a valid one without needing a get_token task at all.
id: api_callnamespace: company.team
tasks: - id: call_api type: io.kestra.plugin.core.http.Request uri: https://api.example.com/v1/data options: auth: type: BEARER token: "{{ credential('my_oauth') }}" retry: type: constant maxAttempts: 3 interval: PT1SRetry types
constant
Retries at fixed intervals. Example: with interval: PT10M, retries occur every 10 minutes.
| Name | Type | Description |
|---|---|---|
interval | Duration | Delay between attempts. |
exponential
Wait time increases after each retry (e.g., 30s, 1m, 2m, …).
| Name | Type | Description |
|---|---|---|
interval | Duration | Base interval between attempts. |
maxInterval | Duration | Maximum interval allowed. |
delayFactor | Double | Multiplier (default: 2). Example: interval 30s → 30s, 1m, 2m, 4m… |
random
Randomized delays within bounds.
| Name | Type | Description |
|---|---|---|
minInterval | Duration | Minimum delay. |
maxInterval | Duration | Maximum delay. |
Configuring retries globally
You can configure retries globally for all tasks in Kestra:
kestra: plugins: configurations: - type: io.kestra values: retry: type: constant maxAttempts: 3 interval: PT30SFlow-level retries
Flow-level retries restart either the entire execution or only failed tasks, controlled by the behavior property:
CREATE_NEW_EXECUTION: Start a new execution.RETRY_FAILED_TASK: Retry only the failed task.
id: flow_level_retrynamespace: company.team
retry: maxAttempts: 3 behavior: CREATE_NEW_EXECUTION # or RETRY_FAILED_TASK type: constant interval: PT1S
tasks: - id: fail_1 type: io.kestra.plugin.core.execution.Fail allowFailure: true
- id: fail_2 type: io.kestra.plugin.core.execution.Fail- With
CREATE_NEW_EXECUTION, the execution attempt increases. - With
RETRY_FAILED_TASK, only the task run attempt increases.
Flow-level retries also restart Subflows as new executions.
Retry vs. Restart vs. Replay
Retry is the only automatic mechanism. Restart and Replay are both manual, initiated from the UI.
| Concept | Scope | Trigger | New execution? |
|---|---|---|---|
| Retry | Task level | Automatic | No |
| Restart | Flow level | Manual | No |
| Replay | Flow or task level | Manual | Yes |
Restart reruns only the failed tasks within the same execution, keeping the same execution ID. Restart is available from the Execution overview page.
Replay starts a new execution from any task (successful or failed) and assigns it a new execution ID. Previous task outputs are reused from cache when available. Replay is available from the Actions menu on the Execution overview page and from task nodes in the Topology, Gantt, or Logs view. See the Replay documentation.
After a replay, the new execution’s Overview tab shows an Original Execution field linking back to the source run.
Was this page helpful?