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.PlatformService
open Axial.State
open Axial.Telemetry
open Axial.Telemetry.JavaScriptError Handling
A Flow has a typed channel for failures the caller is expected to handle:
> type PaymentError = CardDeclined | AccountClosed;;
> let charge () : Flow<PaymentError, decimal> = Flow.fail CardDeclined;;
> Flow.run () (charge ());;val it: Exit<decimal,PaymentError> = Failure (Fail CardDeclined)Core_04-error-handling__index.md_fsharp-1.PaymentErrorCardDeclinedAccountClosedcharge: unit -> Flow<PaymentError,decimal>FlowA flow that requires no environment and can fail with a typed error.
decimalAn abbreviation for the CLI type . Basic Types
Axial.Flowfail: 'error -> Flow<'env,'error,'value>Same as error. The error value to wrap in a failing flow. A flow that always fails with the provided error. let result = Flow.fail "error" |> Flow.run () // result = Failure (Cause.Fail "error")
run: 'env -> Flow<'env,'error,'value> -> Exit<'value,'error>Runs the workflow and blocks until the final exit is available. The environment used by the workflow. The workflow to run. The final workflow exit. let exit = workflow |> Flow.run environment
Unexpected exceptions are defects. The execution outcome retains them outside the workflow's typed error channel:
> open System;;
> type PaymentError = CardDeclined | AccountClosed;;
> let broken () : Flow<PaymentError, decimal> = Flow.die (InvalidOperationException "broken invariant");;
> match Flow.run () (broken ()) with Exit.Failure (Cause.Die error) -> error.Message | _ -> "";;val it: string = "broken invariant"SystemCore_04-error-handling__index.md_fsharp-2.PaymentErrorCardDeclinedAccountClosedbroken: unit -> Flow<PaymentError,decimal>FlowA flow that requires no environment and can fail with a typed error.
decimalAn abbreviation for the CLI type . Basic Types
Axial.Flowdie: exn -> Flow<'env,'error,'value>Creates a defective flow that fails with an exception. The exception representing the defect. A flow that always dies with the provided exception. This is the public constructor for non-domain defects. Use fail for expected typed failures and die when the workflow should surface a bug or panic.
``.ctor``: string -> unitInitializes a new instance of the class with a specified error message. The message that describes the error.
run: 'env -> Flow<'env,'error,'value> -> Exit<'value,'error>Runs the workflow and blocks until the final exit is available. The environment used by the workflow. The workflow to run. The final workflow exit. let exit = workflow |> Flow.run environment
Axial.Exit`2Represents the final outcome of a workflow execution. The type of the success value. The type of the domain-specific failure value.
FailureThe workflow failed due to a specific cause.
Axial.Cause`1Represents the cause of a failed workflow. The type of the domain-specific failure value.
DieAn unexpected defect or panic (e.g., an exception).
error: exnMessage: stringGets a message that describes the current exception. The error message that explains the reason for the exception, or an empty string ("").
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.
Use Flow.recover when a typed failure needs a fallback with a different
error type, Flow.orElseWith when it keeps the same error type, and
Flow.fold to inspect every cause. See
Recovery and compound causes for what happens when error types change and when a handler throws.
Show page setup
// Setup for the checked examples on this page.
open Axial
/// Fails the docs test when an example's result differs from the value shown.
let shouldEqual expected actual =
if actual <> expected then failwithf "Expected %A but got %A" expected actualtype PaymentError = CardDeclined | AccountClosed
let declined : Flow<PaymentError, decimal> = Flow.fail CardDeclined
let broken : Flow<PaymentError, decimal> = Flow.die (InvalidOperationException "boom")
FsLiveDocsGeneratedPage17_2D306DEB1823.PaymentErrorCardDeclinedAccountCloseddeclined: Flow<PaymentError,decimal>FlowA flow that requires no environment and can fail with a typed error.
decimalAn abbreviation for the CLI type . Basic Types
Axial.Flowfail: 'error -> Flow<'env,'error,'value>Same as error. The error value to wrap in a failing flow. A flow that always fails with the provided error. let result = Flow.fail "error" |> Flow.run () // result = Failure (Cause.Fail "error")
broken: Flow<PaymentError,decimal>die: exn -> Flow<'env,'error,'value>Creates a defective flow that fails with an exception. The exception representing the defect. A flow that always dies with the provided exception. This is the public constructor for non-domain defects. Use fail for expected typed failures and die when the workflow should surface a bug or panic.
``.ctor``: string -> unitInitializes a new instance of the class with a specified error message. The message that describes the error.
Requires & types
Requires: open Axial (packages: Axial)val declined: Flow<PaymentError,decimal>val broken: Flow<PaymentError,decimal>// orElseWith recovers a typed failure and keeps the same error type.
declined
|> Flow.orElseWith (fun _ -> Flow.ok 0m)
|> Flow.run ()
|> shouldEqual (Exit.Success 0m : Exit<decimal, PaymentError>)
// recover also recovers a typed failure but may change the error type.
declined
|> Flow.recover (fun _ -> Flow.ok 0m)
|> Flow.run ()
|> shouldEqual (Exit.Success 0m : Exit<decimal, Never>)
// Neither handles a defect; fold sees every cause, including defects.
broken
|> Flow.orElseWith (fun _ -> Flow.ok 0m)
|> Flow.run ()
|> function
| Exit.Failure(Cause.Die error) -> shouldEqual "boom" error.Message
| other -> failwithf "expected a defect, got %A" other
broken
|> Flow.fold (fun value -> Flow.ok $"value {value}") (fun cause -> Flow.ok (Cause.prettyPrint string cause))
|> Flow.run ()
|> shouldEqual (Exit.Success "Die(InvalidOperationException: boom)")
declined: Flow<PaymentError,decimal>(|>): 'T1 -> ('T1 -> 'U) -> 'UApply a function to a value, the value being on the left, the function on the right The argument. The function. The function result. let doubleIt x = x * 2 3 |> doubleIt // Evaluates to 6
Axial.FloworElseWith: ('error -> Flow<'env,'error,'value>) -> Flow<'env,'error,'value> -> Flow<'env,'error,'value>Computes a fallback flow from the typed error when the source flow fails. The fallback runs only for expected typed failures represented by Cause.Fail. It does not catch interruption or defects. Use this for domain-level recovery, not for swallowing cancellation or unexpected exceptions. A function that produces a new flow from the error value. The source flow. A flow that recovers from errors using the fallback function. let flow = Flow.fail "error" |> Flow.orElseWith (fun err -> Flow.succeed "recovered")
ok: 'value -> Flow<'env,'error,'value>Creates a successful synchronous flow. The value to wrap in a successful flow. A flow that always succeeds with the provided value.
run: 'env -> Flow<'env,'error,'value> -> Exit<'value,'error>Runs the workflow and blocks until the final exit is available. The environment used by the workflow. The workflow to run. The final workflow exit. let exit = workflow |> Flow.run environment
shouldEqual: 'a -> 'a -> unitAxial.Exit`2Represents the final outcome of a workflow execution. The type of the success value. The type of the domain-specific failure value.
SuccessThe workflow completed successfully.
decimalAn abbreviation for the CLI type . Basic Types
FsLiveDocsGeneratedPage17_2D306DEB1823.PaymentErrorrecover: ('error -> Flow<'env,'nextError,'value>) -> Flow<'env,'error,'value> -> Flow<'env,'nextError,'value>Axial.NeverRepresents an error channel that cannot occur.
broken: Flow<PaymentError,decimal>FailureThe workflow failed due to a specific cause.
Axial.Cause`1Represents the cause of a failed workflow. The type of the domain-specific failure value.
DieAn unexpected defect or panic (e.g., an exception).
error: exnMessage: stringGets a message that describes the current exception. The error message that explains the reason for the exception, or an empty string ("").
other: Exit<decimal,PaymentError>failwithf: Printf.StringFormat<'T,'Result> -> 'TPrint to a string buffer and raise an exception with the given result. Helper printers must return strings. The formatter. The formatted result. See Printf.failwithf (link: ) for examples.
fold: ('value -> Flow<'env,'nextError,'next>) -> (Cause<'error> -> Flow<'env,'nextError,'next>) -> Flow<'env,'error,'value> -> Flow<'env,'nextError,'next>Folds both the successful value and the failure cause into a new flow. Use this to branch on the full outcome of a flow, including interruptions and defects. A function that returns a new flow from the success value. A function that returns a new flow from the failure cause. The source flow. A flow that continues with the outcome of either or .
value: decimalcause: Cause<PaymentError>Axial.CauseprettyPrint: ('error -> string) -> Cause<'error> -> stringPretty prints a cause tree for diagnostics.
string: 'T -> stringConverts the argument to a string using ToString. For standard integer and floating point values and any type that implements IFormattable, ToString conversion uses CultureInfo.InvariantCulture. The input value. The converted string. string 'A' // evaluates to "A" string 0xff // evaluates to "255" string -10 // evaluates to "-10"
Requires & types
Requires: open Axial (packages: Axial)Exit.toResult loses information. Use it only at a boundary that has decided how to represent defects, interruption,
and combined causes.
Learn more
- Bind explains how to assign or map an error at a
flow { }bind site. - Policy and verification explains reusable verification rules and
Flow.verify. - Defects covers exception capture and intentional recovery in detail.
- Cause reference lists cause transformations and rendering.
- Supervision explains how unjoined child defects are reported.

