Skip to content

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.