Repository F# setup
open System
open System.IO
open System.Threading
open System.Threading.Tasks
open Axial
open Axial.Layers
open Axial.Console
open Axial.FileSystem
open Axial.Hosting
open Axial.Hosting.Browser
open Axial.Hosting.Node
open Axial.HttpClient
open Axial.PlatformService
open Axial.Process
open Axial.State
open Axial.Telemetry
open Axial.Telemetry.JavaScript

Error Handling

A Flow has a typed channel for failures the caller is expected to handle:

type PaymentError = CardDeclined | AccountClosed

let charge : Flow<PaymentError, Receipt> =
    Flow.fail CardDeclined
Unexpected exceptions are defects. They are retained in the execution outcome rather than being added silently to the workflow's typed error:
Flow.die (InvalidOperationException "broken invariant")
An Exit distinguishes the cases:
Cause Meaning
Cause.Fail error Expected typed failure
Cause.Die exception Unexpected defect
Cause.Interrupt Cooperative cancellation or interruption
Cause.Then (first, second) Sequentially combined causes
Cause.Both (left, right) Concurrently combined causes
Cause.Traced (cause, trace) Cause with diagnostic context

Use an attempt constructor only when an exception from an interop API is an expected outcome. Use Flow.catch only when the application deliberately translates a defect into a typed error.

Exit.toResult is intentionally lossy. Use it only at a boundary that has decided how defects, interruption, and combined causes should be represented.

Learn more