<@ULVA73B9P> Is there a way for a flow run to indi...
# ask-marvin
n
@Marvin Is there a way for a flow run to indicate that it was un-successful without throwing an error?
m
thought for 117.5 seconds
Yes — in Prefect 3.x, a flow can finish in a non-success state without raising an exception by returning a state object. For example:
Copy code
python
from prefect import flow
from prefect.states import Failed, Cancelled

@flow
def my_flow(should_fail: bool):
    if should_fail:
        return Failed(message="Validation failed")
    return "ok"
Then:
Copy code
python
state = my_flow(True, return_state=True)
print(state.type)  # FAILED
A few useful notes: *
return Failed(...)
marks the flow run as failed without throwing Python errors * You can also return
Cancelled(...)
,
Paused(...)
, etc. * If you don’t use
return_state=True
, Prefect will normally give you the flow result, not the state object A common pattern is:
Copy code
python
from prefect import flow
from prefect.states import Failed, Completed

@flow
def check_inputs(x):
    if x < 0:
        return Failed(message="x must be non-negative")
    return Completed(message="Inputs look good")
If you want, you can also attach data:
Copy code
python
from prefect.states import Failed

return Failed(
    message="Business rule failed",
    data={"reason": "customer inactive"}
)
One caveat: Returning a state object is supported, but it’s best used when you intentionally want to control the final run state. If you just want to stop early but still be considered successful, return a normal value instead. Relevant docs/source-backed behavior: * Prefect flow concepts: https://docs.prefect.io/ * Deployment/flow patterns in Prefect 3.x: https://docs.prefect.io/v3/ If you want, I can also show the difference between: 1. raising an exception, 2. returning
Failed(...)
, and 3. handling a failed task while keeping the flow successful.
n
I have an automation in prefect dashboard that sends an alert email when a flow enters a
Failed
state. If I return the
Failed()
object like you described above, will it trigger the alert via the automation? My goal in asking you this question was to find a way to mark a flow as failed without sending us an alert @Marvin
m
thought for 11.2 seconds
Yes — if your flow run ends in a
Failed
state
, an automation that triggers when a flow enters
Failed
should still fire, even if you got there by
return Failed(...)
instead of raising an exception. So for your goal:
return Failed(...)
is not a good way to suppress a failure alert.
From Prefect’s perspective, the run is still failed. The automation reacts to the state transition, not to whether Python raised an error. If you want the run to be unsuccessful in a business sense but not trigger a
Failed
automation
, you generally have a few options: 1. Return a successful state/value and encode the business outcome in the result/logs * e.g. return
"no data to process"
or a structured object like
{"status": "rejected"}
* the flow run will be
Completed
, so the
Failed
automation will not fire 2. Use a different non-failure state if it matches your semantics *
Cancelled
or
Paused
are different states, so a
Failed
automation would not match them * but only use these if they accurately describe what happened 3. Change the automation logic * If some failures are expected, the cleanest solution is often to refine the automation so it alerts only on the failures you care about * for example, based on tags, deployment, work pool, or other available event criteria in the automation UI For your use case, the most common pattern is: Keep the flow in
Completed
Log clearly that the business outcome was not successful Optionally return structured metadata describing the outcome Example:
Copy code
python
from prefect import flow, get_run_logger

@flow
def my_flow(records):
    logger = get_run_logger()

    if not records:
        logger.warning("Flow completed without processing records")
        return {
            "status": "no-op",
            "reason": "No records found"
        }

    # normal work here
    return {
        "status": "processed",
        "count": len(records)
    }
That will not trigger a
Failed
-state automation. If you'd like, I can help you design a pattern for business failure vs orchestration failure in Prefect so only true operational problems send alerts.