Scott Pedersen
09/19/2025, 4:31 AMMarvin
09/19/2025, 4:31 AMMarvin
09/19/2025, 4:34 AM.result()
on the PrefectFuture
.
In Prefect 3.x:
- .result()
blocks until the task finishes and returns the original value, so you can use it directly in an if
check.
- You can control behavior with timeout
and raise_on_failure
.
Examples:
from prefect import flow, task
@task
def is_ready(x):
return x > 0
@flow
def main():
fut = is_ready.submit(5)
# Basic: raises if the task failed
flag = fut.result()
if flag:
print("Result is True")
else:
print("Result is False")
Handle failures explicitly:
try:
flag = fut.result(timeout=30) # seconds
if flag:
...
except Exception as exc:
# The task failed or timed out
...
Non-raising variant (inspect state yourself):
flag = fut.result(raise_on_failure=False)
if fut.state.is_failed():
# handle failure
else:
if flag:
...
Resolve futures in nested structures:
from prefect.futures import resolve_futures_to_results
flag = resolve_futures_to_results(fut)
if flag:
...
Tip: Don’t check the future itself (e.g., if fut:
) — that won’t resolve it. Always use fut.result()
(or resolve_futures_to_results
).Scott Pedersen
09/19/2025, 4:36 AMMarvin
09/19/2025, 4:37 AMMarvin
09/19/2025, 4:37 AMPrefectFuture.result()
the same way:
- future.result()
blocks and returns the underlying value (so you can check True/False directly)
- Supports timeout
and raise_on_failure
Example:
from prefect import flow, task
@task
def is_ready(x):
return x > 0
@flow
def main():
fut = is_ready.submit(5)
flag = fut.result(timeout=30, raise_on_failure=True)
if flag:
print("Result is True")
else:
print("Result is False")
If you want to avoid raising on failure and inspect the state:
flag = fut.result(raise_on_failure=False)
state = fut.state
if state.is_failed():
# handle failure
else:
if flag:
...
If you have futures nested in structures, prefect.futures.resolve_futures_to_results(...)
is also available in 2.20.16.
Note: Prefect 3.x keeps this pattern; consider upgrading when you’re ready.Scott Pedersen
09/19/2025, 4:39 AMif fut.result() is False:
...
Marvin
09/19/2025, 4:39 AMMarvin
09/19/2025, 4:40 AMfut.result()
and then check the boolean.
- If you need to distinguish a task failure from a False result (and avoid an exception), use fut.result(raise_on_failure=False)
and inspect the state first.
Patterns:
1) Simplest (treat failure as error)
flag = fut.result() # raises if the task failed
if flag is False: # or: if not flag
...
2) Distinguish failure from False
flag = fut.result(raise_on_failure=False)
if fut.state.is_failed():
# handle the failure path
else:
if flag is False: # or: if not flag
...
Notes:
- is_completed()
only tells you the task succeeded; you still need .result()
to read the value.
- Using is False
is a strict boolean check; use if not flag
if you want to treat other falsy values (0, "", [], None) the same as False.
If you share whether you want to handle failures differently from a False result or avoid blocking, I can tailor the pattern further.Scott Pedersen
09/19/2025, 4:44 AMif not fut.result():
...
and on for one of the futures it didn't equate to True
so I used instead.
if fut.result() is False:
...
What could be the reason for this?Marvin
09/19/2025, 4:44 AMMarvin
09/19/2025, 4:45 AMreturn bool(value)
- Choose your check based on intent:
- Treat any falsy value as negative:
flag = fut.result()
if not flag:
...
- Only treat literal False as negative:
flag = fut.result()
if flag is False:
...
- If you need to distinguish failures from False, avoid exceptions:
flag = fut.result(raise_on_failure=False)
if fut.state.is_failed():
# handle failure
elif flag is False:
...
If you can, print the actual type/value to confirm what you’re getting:
val = fut.result()
print(type(val), repr(val))
Share that output and I can suggest the most robust check for your case.Scott Pedersen
09/19/2025, 4:47 AMState
objectMarvin
09/19/2025, 4:47 AMMarvin
09/19/2025, 4:49 AMfut.result()
gives you whatever the task returned. If your task returns a Prefect State
, then:
- not fut.result()
is checking the truthiness of a State object (custom objects are truthy by default), so it will be False.
- fut.result() is False
checks identity with the singleton `False`; a State
object is never the False
object, so this will also be False.
In other words, both checks aren’t looking at the boolean you care about—they’re just looking at the fact you returned a State
object.
What to do instead depends on your intent:
A) You want to know if the task execution succeeded/failed
- Check the future’s run state (not the returned value):
if fut.state.is_failed():
...
elif fut.state.is_completed():
...
B) You want a True/False value produced by the task
- Don’t return a State
from the task—return a real boolean:
@task
def is_ready(...):
return bool(some_condition)
flag = fut.result()
if not flag:
...
C) You intentionally returned a State and need the value inside it
- Extract the inner value from that returned State:
from prefect.states import get_state_result
inner_state = fut.result() # this is a State
value = get_state_result(inner_state, raise_on_failure=False)
if inner_state.is_failed():
# handle inner failure
elif value is False:
...
Important note: Returning a State
from a task does not set the task’s run state—Prefect manages the run state separately. Use exceptions to fail a task or just return your data value (e.g., a bool) and inspect it.Scott Pedersen
09/19/2025, 4:53 AMCompleted()
or Failed(message="Failed to do xyz")
should I be doing the following?
if fut.state.is_failed():
...
elif fut.state.is_completed():
...
Marvin
09/19/2025, 4:53 AMMarvin
09/19/2025, 4:53 AMif fut.state.is_failed():
...
elif fut.state.is_completed():
...
- If your task returns a State object as its value (e.g., Completed()
or Failed("...")
), then you need to inspect the returned value, not `fut.state`:
inner = fut.result() # this is a State returned by your task
if inner.is_failed():
...
elif inner.is_completed():
...
Important nuance:
- fut.state
is the orchestration state of the task run. It will usually be Completed if the task executed and returned a value—even if that value is a Failed(...)
State object that you created. In that case, fut.state.is_completed()
would be True, because the run succeeded in returning a value.
- Returning Prefect State objects from tasks is generally not recommended; it’s easy to confuse “run state” with “returned value”. Prefer to:
- Return a real boolean and check it:
flag = fut.result()
if not flag:
...
- Or fail the task by raising an exception (so fut.state.is_failed()
becomes True and fut.result()
raises):
@task
def do_thing(...):
if bad_condition:
raise RuntimeError("Failed to do xyz")
return True
If you truly need to return a State and then read its payload:
from prefect.states import get_state_result
inner = fut.result() # a State
value = get_state_result(inner, raise_on_failure=False)
if inner.is_failed():
# handle inner failure/message
elif inner.is_completed():
# use value