Failures, Exits, and Causes
Durable workflows do not collapse every non-success into an exception string.
Expected Failure
The E in Workflow<I, O, E> is a business failure that callers are expected to understand:
dart
workflow.fail(OrderFailure.creditDeclined(order.id));The failure value is encoded through the definition's Schema<E> and survives storage and replay.
Terminal Exit
WorkflowHandler.exitOf(run) returns:
text
WorkflowExit<O, E>
├─ WorkflowSuccess<O, E>
└─ WorkflowFailure<O, E>
└─ WorkflowCause<E>WorkflowCause<E> distinguishes:
ExpectedWorkflowFailure<E>for modeled business rejection;WorkflowDefect<E>for unexpected implementation failure;WorkflowCancellation<E>for requested cancellation;WorkflowTimeout<E>for a bounded operation that expired;CompositeWorkflowCause<E>for structured parallel failure.
Operation Failure
An operation reports a typed expected failure through OperationExecution.fail:
dart
reserve.implement((operation, order) async {
final result = await gateway.reserve(order);
if (result.declined) {
operation.fail(
OrderFailure.inventoryUnavailable(order.id),
retryable: false,
);
}
return result.reservation;
});Retryability is operational policy. The expected failure payload remains domain data.
Recovery Is Not Failure Modeling
retryOperation and redrive are audited operator actions. They do not mutate history or reinterpret a defect as an expected failure.