when returned false, or a dependency was missing).
Skipped vs failed
| State | Cause | Dependents |
|---|---|---|
| Skipped | when returned False, or step_span() hit a skipped upstream step (SpanNotFound) | Steps that need that step’s data are skipped; steps with only depends_on wait and may still run |
| Failed | Handler raised, step returned OutputEvent with error, or param/when evaluation failed | Steps that try to read the failed step’s output fail during evaluation; workflow ends with status.code == "error" |
Step failure
When a step handler raises, Timbal records the error on that step’s span and marks the workflow failed:Dependent steps
A downstream step that reads a failed step’s output viastep_span() fails during parameter resolution (before its handler runs):
step_span("name", default=None) when a step might have been skipped (see Control flow), not when it failed. A failed upstream step does not produce output to read.
Skipped branches
Whenwhen is false, the step is skipped and dependents that require its output are skipped too:
process and save_results are skipped.
Steps that only need ordering (not data) can use depends_on to run after a branch resolves:
Pauses (approval / suspend)
When a step hits an approval gate orsuspend(), the workflow pauses with status.code == "cancelled" and a reason like approval_required or input_required. Parallel steps that also pause emit their events before the workflow stops, so you can resume multiple pending ids in one call.
Pauses are not failures. Resume with parent_id and resume={...} as documented in Resuming a paused run.
Cycle detection
Linking steps that would create a cycle raises immediately when you call.step():
depends_on, when callables, and lambda parameters that call step_span().
Tracing
Every step gets its own span under the workflow span. Inspect per-step input, output, and errors viaget_run_context()._trace or your tracing provider. Failed steps record error on their span even when the workflow’s final status is error.
See also
- Control flow — optional steps with
default=None - Branching — conditional execution
- Human in the loop — pauses on workflow steps