# On error paths

> Add inline recovery branches, share recovery steps, and reconnect them to the main flow.

An **On error** connection follows a step's failure after its retries finish.
Use its branch to send a notification, record a failure, clean up resources,
or recover and continue the workflow. Error branches live on the same canvas
as the ordinary success path.

## Add an error path

Select the step whose failure you want to handle and open **If this step
fails**. Add a recovery step or connect to an existing step. Extend that branch
with ordinary connections, or reconnect it to a step already on the main path.

For example, Fetch can connect normally to Process and through **On error** to
Use cached data. Connect Use cached data to Process as well. Process then runs
once: after Fetch succeeds, or after the recovery branch succeeds when Fetch
fails. The recovery branch stays skipped when Fetch succeeds.

You can connect the same source to a target with both a normal connection and
an **On error** connection when that target should handle either outcome.
Cycles remain disallowed.

## Share recovery logic

Several sources can point to the same recovery step. The shared step waits for
its incoming dependencies to resolve and runs once per workflow run when a
failure activates its error path. If several sources fail, it receives all of
those failures; it does not run separately for each one.

A skipped branch does not count as a failure and does not activate an **On
error** connection. Recovery steps can have their own error paths, and separate
error branches can merge or reconnect to the main flow.

## Choose what happens after an error step

Choose one of two outcomes after the recovery step:

| Outcome | Behavior after the step succeeds |
|---|---|
| **Follow connections** | Continue along the step's outgoing connections. This is the default. |
| **Fail workflow** | Finish this step, then fail the run before its successors execute. |

The failure outcome applies when the step handles an active error. Reaching the
same step through an ordinary success path does not fail the run. Choose
**Fail workflow** for an action such as notifying or cleaning up when the run
must remain failed.

If an error branch finishes successfully and no unhandled error remains, the
run can complete. A recovery step that fails needs its own **On error** path;
otherwise the workflow fails.

## Read the failure context

Templates and formulas on error paths can use:

| Field | Value |
|---|---|
| `error.step_id` | A failed source step's ID. |
| `error.step_identifier` | That source's reference name. |
| `error.input` | The input being processed by that failed source. |
| `error.reason` | The failure reason. |
| `error.failures` | The list of failure contexts when error paths merge. |

For example, a notification can include `{{error.step_identifier}}` and
`{{error.reason}}`. Shared recovery logic can iterate over `error.failures` to
handle every failed source.

After an error path rejoins a normal path, error context is optional: it is
present when recovery was needed and absent when the normal path succeeded.
Use the upstream step outputs for ordinary data and account for missing error
context in expressions at those joins.

## Recovery does not undo earlier work

An **On error** path reacts to failure of its connected source. It does not
automatically undo changes made by steps that succeeded earlier. Add explicit
cleanup actions to the relevant error path when needed, and choose **Fail
workflow** after the last cleanup step when the run must remain failed.

## Next step

[Retries](/help/workflows/retries) explains when a step tries again before its
error path runs.
