Mehdi Lallouache
12/26/2025, 8:59 AMMarvin
12/26/2025, 8:59 AMMarvin
12/26/2025, 9:05 AMallow_failure
- This tells Prefect to allow a failed upstream input and passes the exception into the downstream task as the value.
- Example:
from prefect import flow, task
from prefect.utilities.annotations import allow_failure
@task
def risky():
raise ValueError("boom")
@task
def handle(x):
if isinstance(x, Exception):
return "handled failure"
return x
@flow
def my_flow():
fut = risky()
return handle(allow_failure(fut))
- Docs: allow_failure annotation
- If you want to inspect a task’s outcome in the flow without raising: use future.result(raise_on_failure=False)
- This returns the exception object instead of raising it so your flow can keep going.
from prefect import flow, task
@task
def risky():
raise ValueError("boom")
@flow
def my_flow():
fut = risky()
res = fut.result(raise_on_failure=False)
if isinstance(res, Exception):
# log or fallback
return "recovered"
return res
- Docs: prefect.futures and PrefectFuture.result
- If the error is transient: use retries (optionally with backoff or conditions)
- This doesn’t “hide” failures, but it reduces them.
from prefect import task
from prefect.tasks import exponential_backoff
@task(retries=3, retry_delay_seconds=exponential_backoff(2))
def sometimes_flaky():
...
- Docs: Retries guide
- Try/except inside the task is okay, but be aware of trade-offs
- If you swallow errors inside the task and return a fallback, Prefect will mark the task as COMPLETED. That can hide genuine failures from monitoring/alerting.
- Prefer letting the task fail and handling it at the flow/dependency boundary with allow_failure or result(raise_on_failure=False) when you want observability of failures.
A few behavioral notes:
- By default, a failed upstream blocks dependent tasks (raising UpstreamTaskError). allow_failure bypasses that for specific dependencies.
- Docs: UpstreamTaskError
- The flow does not “stop” globally when a task fails; other independent branches continue. The flow will be marked failed if you resolve/return a failed future without handling it. If you want the flow to finish “successfully” despite certain task failures, handle those failures and avoid returning unresolved failed futures from the flow.
If you can share your specific pattern (e.g., “task B depends on task A but should still run when A fails” vs. “I just don’t want the whole flow to fail if some tasks crash”), I can suggest the cleanest snippet for your case.