Chris Marriott
08/12/2026, 8:23 AMMarvin
08/12/2026, 8:23 AMMarvin
08/12/2026, 8:24 AMCompleted with Errors or Completed with Warnings.
Built-in state types are things like:
- COMPLETED
- FAILED
- RUNNING
- PENDING
- SCHEDULED
- CANCELLED
- CRASHED
- PAUSED
- CANCELLING
So if you're asking whether Prefect has a first-class orchestration state for “success, but imperfect” — no, not as a distinct built-in state type.
What people usually do instead is one of these:
- return a COMPLETED state with a custom message
- use a custom name like CompletedWithWarnings
- include warning/error details in the result or state.data
- explicitly fail if “partial success” should be treated as operational failure
Example pattern:
from prefect.states import Completed
return Completed(
name="CompletedWithWarnings",
message="Loaded 95/100 records; 5 were skipped",
data={"skipped": 5, "errors": [...]}
)
That will still behave as a completed run from Prefect’s perspective, but gives you richer context in the UI / API.
So the short answer is:
- No built-in Completed with Errors/Warnings state type
- Yes, you can represent that semantic with a custom completed state name/message/data
If you want, I can also show the best practice pattern for:
1. task-level partial failures, or
2. flow-level “green but needs attention” reporting.Chris Marriott
08/12/2026, 8:25 AMMarvin
08/12/2026, 8:26 AMMarvin
08/12/2026, 8:26 AMFAILED when downstream orchestration should treat the run as unsuccessful
- Use COMPLETED when the run should stay green, even if there were recoverable issues
- Put the nuance in the result, state message, logs, or a custom state name
---
1. Best practice for task-level partial failures
This is the cleanest pattern when a task processes many items and some fail, but you do not want the whole task to fail.
Have the task:
- catch per-item exceptions
- collect successes and failures
- return a structured result
- optionally return a custom Completed(...) state if you want UI messaging
Example:
from dataclasses import dataclass
from prefect import task, flow
from prefect.states import Completed
@dataclass
class BatchResult:
succeeded: list
failed: list
@task
def process_batch(items):
succeeded = []
failed = []
for item in items:
try:
result = item * 2 # replace with real work
succeeded.append({"item": item, "result": result})
except Exception as exc:
failed.append({"item": item, "error": str(exc)})
return Completed(
name="CompletedWithWarnings" if failed else "Completed",
message=f"{len(succeeded)} succeeded, {len(failed)} failed",
data=BatchResult(succeeded=succeeded, failed=failed),
)
@flow
def my_flow():
state = process_batch([1, 2, 3], return_state=True)
result = state.result()
print(result.succeeded)
print(result.failed)
Why this is good:
- the task remains green if partial failure is acceptable
- the failure details are explicit and structured
- the flow can inspect and decide what to do next
Even simpler option: just return a normal Python object instead of a custom state:
from prefect import task
@task
def process_batch(items):
succeeded = []
failed = []
for item in items:
try:
succeeded.append(item * 2)
except Exception as exc:
failed.append({"item": item, "error": str(exc)})
return {
"succeeded": succeeded,
"failed": failed,
"warning": f"{len(failed)} items failed" if failed else None,
}
This is often the best default unless you specifically want the state/message shown in the UI.
---
Recommended guideline for task-level partial failures
Use a normal return value when:
- consumers of the task need structured output
- partial failure is part of expected business logic
Use a custom Completed(...) state when:
- you want the Prefect UI state/message to clearly show warnings
- you want operators to notice “green, but imperfect” runs quickly
Use FAILED when:
- any partial failure should stop downstream work
- data quality requires all-or-nothing behavior
---
2. Best practice for flow-level “green but needs attention” reporting
This is usually best handled by:
- aggregating warning/error counts from tasks
- logging clearly
- finishing the flow as COMPLETED
- optionally returning a custom completed state for a UI-visible summary
Example:
```
from prefect import flow, task
from prefect.states import Completed
from prefect.logging import get_run_logger
@task
def extract():
return {
"records_read": 100,
"warnings": ["2 malformed rows skipped"],
"errors": []
}
@task
def transform(data):
return {
"records_written": 98,
"warnings": ["1 duplicate dropped"],
"errors": []
}
@flow
def etl_flow():
logger = get_run_logger()
extract_result = extract()
transform_result = transform(extract_result)
warnings = []
errors = []
warnings.extend(extract_result.get("warnings", []))
warnings.extend(transform_result.get("warnings", []))
errors.extend(extract_result.get("errors", []))
errors.extend(transform_result.get("errors", []))
if warnings:Marvin
08/12/2026, 8:26 AMThis gives you:
- a green flow run
- a visible warning-oriented state name/message
- structured metadata for later inspection
---
*What I’d recommend in most real projects*
*For tasks:*
- return structured data like:
- `processed_count`
- `failed_count`
- `failures`
- `warnings`
- only use `Completed(...)` if the UI signal matters
*For flows:*
- aggregate those task outputs
- log warnings prominently
- optionally return a final custom completed state like `CompletedWithWarnings`
---
*Practical result shape*
A good reusable shape is something like:
{
"ok": true,
"warning_count": 3,
"error_count": 1,
"warnings": [...],
"errors": [...],
"metrics": {...}
}
```
That tends to be easier to work with than trying to encode too much business meaning into Prefect states themselves.
---
Important caveat
If you return Completed(...), Prefect orchestration will treat that as success. So do not use this pattern if you need:
- retries
- failure notifications
- downstream prevention on bad data
In those cases, fail the task/flow and put the details in the exception, logs, or result data.
---
My actual “best practice” summary
- Business-level partial success → return structured results, optionally CompletedWithWarnings
- Operational failure → raise / fail the run
- Need green but visible attention → Completed(name="CompletedWithWarnings", message=...)
- Need automation on warnings → emit logs/metrics or build automations around messages/tags/results, not around a special built-in warning state
If you want, I can give you a production-ready helper pattern like a reusable WarningSummary model plus a decorator/util for standardizing this across all flows.Chris Marriott
08/12/2026, 8:29 AMMarvin
08/12/2026, 8:29 AMMarvin
08/12/2026, 8:30 AMCOMPLETED.
What changes is the display name/message.
So if you do:
from prefect.states import Completed
return Completed(
name="CompletedWithWarnings",
message="95 succeeded, 5 skipped"
)
in the UI you should expect roughly:
- the run is shown as successful/completed
- it uses the visual treatment of a completed run, not failed/warning-specific orchestration styling
- the custom name CompletedWithWarnings can appear as the state name
- the message 95 succeeded, 5 skipped can appear in the run details / state details
So operationally it is still “green,” just with more descriptive labeling.
Important implication: if your team scans the UI primarily by color/status, this will not stand out the same way a failed run would. It’s more of a “green with text context” pattern, not a separate warning severity.
If you want stronger visibility, common additions are:
- log a warning in the flow/task logs
- include warning counts in the run name or deployment naming conventions
- use automations based on logs/events/results if needed
- persist a structured summary in the result data
If you'd like, I can show a small screenshot-equivalent mental model of where state type, name, and message tend to show up in the Prefect UI/API, or give you a tiny flow you can run locally to see it.Chris Marriott
08/12/2026, 8:31 AMMarvin
08/12/2026, 8:31 AMMarvin
08/12/2026, 8:31 AMCompleted(name="CompletedWithWarnings", ...)
the run’s type is still COMPLETED. The custom name is just labeling/context on that completed state.
So in practice:
- Filters based on state type/status → it will behave like COMPLETED
- Notification / automation triggers based on run state type → it will also behave like COMPLETED
- it does not create a brand-new canonical state category alongside FAILED, CRASHED, etc.
So if you’re hoping for:
- a dedicated UI filter like CompletedWithWarnings
- a built-in automation trigger like “when state becomes CompletedWithWarnings”
that’s not the usual behavior.
What you may be able to use, depending on where you're filtering/inspecting, is:
- state name as metadata
- state message
- logs
- returned/persisted result data
- events/automations driven by other signals you emit
Best practice if you need notifications for warnings:
1. Keep the flow/task COMPLETED
2. Emit an explicit warning signal elsewhere:
- warning log line
- custom event
- structured result payload
3. Trigger alerting off that signal rather than expecting a new state class
So the conceptual model is:
- state type = orchestration behavior
- state name/message = operator-facing annotation
If you want, I can research the current Prefect Cloud automation/filter capabilities specifically around whether state names (not just types) are exposed in filters/triggers in the current UI/API.Nate
08/12/2026, 4:52 PMallow UI to respect custom state namesthere might be some interesting tidbits to solve, but OTOH seems achievable and useful