Back to examples
Error Handling
Fail Fast
Cancel pending tasks as soon as one task fails.
When to use
Use `fail_fast=True` when a failing task means the rest of the pipeline is pointless. This saves compute and surfaces errors faster.
error-handling/fail-fast.py
"""
06_fail_fast.py: Early pipeline termination with fail_fast=True.
Demonstrates:
- run_local(fail_fast=True): as soon as one task fails, pending tasks are cancelled
- A flow with two independent tasks where one always raises
"""
from dagy import flow, task
@task
def always_succeeds(label: str) -> str:
print(f" {label}: completed successfully")
return f"ok:{label}"
@task
def always_fails(label: str) -> str:
print(f" {label}: about to raise!")
raise RuntimeError(f"Task '{label}' encountered a fatal error")
@flow(name="fail_fast_flow")
def fail_fast_flow() -> None:
always_succeeds("task-A")
always_fails("task-B") # This will fail and trigger fail_fast
always_succeeds("task-C") # Should be cancelled before it runs
if __name__ == "__main__":
from dagy.local.errors import TaskFailedError
try:
result = fail_fast_flow.run_local(fail_fast=True)
print(f"Run ID : {result.run_id}")
print(f"Status : {result.status}")
except TaskFailedError as exc:
# fail_fast=True causes run_local to raise as soon as any task fails.
print(f"Pipeline stopped early (fail_fast=True): {exc}")How it works
- `always_succeeds` completes normally.
- `always_fails` raises a `RuntimeError` immediately.
- `always_succeeds` (task-C) is scheduled after task-B but would be cancelled by fail-fast.
- `run_local(fail_fast=True)` makes the executor stop and raise as soon as any task fails.
- The caller catches `TaskFailedError` to handle early termination gracefully.
Inputs
- None.
Outputs
- A `TaskFailedError` exception (pipeline stops early).
Dependencies
`dagy`, `dagy.local.errors.TaskFailedError`