Troubleshooting Types
This page shows the compiler errors that usually mean you crossed a wrapper boundary in the wrong place.
Most FsFlow type errors are not exotic. The compiler usually sees one wrapper shape and you intended another.
Error: A Unique Overload For Method Bind Could Not Be Determined
This usually happens when the compiler cannot tell which wrapper shape a let! value should use.
Example:
let nested : Async<Async<Result<int, string>>> =
async {
return async { return Ok 42 }
}
let workflow : Flow<unit, string, int> =
flow {
let! next = nested
let! value = next
return value
}
The second let! is ambiguous.
Fix it with a type annotation:
let workflow : Flow<unit, string, int> =
flow {
let! next = nested
let! (value: int) = next
return value
}
Error: The Flow Requires A Different Environment Type
This usually means you wrote a smaller workflow against one env type and are trying to run it inside a larger env.
Example:
type SmallEnv = { Prefix: string }
type BigEnv = { App: SmallEnv; RequestId: string }
let greet : Flow<SmallEnv, string, string> =
flow {
let! prefix = Flow.read _.Prefix
return $"{prefix} world"
}
If you want to run it in BigEnv, derive the smaller local env from the outer one:
let greetInBigEnv : Flow<BigEnv, string, string> =
greet |> Flow.localEnv _.App
Error: Option Or ValueOption Does Not Match Your Error Type
Implicit option binding only works when the workflow error type is unit.
This fails:
let workflow : Flow<unit, string, int> =
flow {
let! value = Some 42
return value
}
Use an explicit adapter when you want a custom error:
let workflow : Flow<unit, string, int> =
Some 42
|> Flow.fromOption "missing value"
Error: ColdTask Does Not Match Task
Flow.fromTask and direct flow { let! ... } support ColdTask<'value> for delayed task work.
ColdTask<'value> means:
CancellationToken -> Task<'value>
Wrap the factory explicitly:
let load : ColdTask<int> =
ColdTask(fun _ -> Task.FromResult 42)
If you already have a started Task<'value>, bind it directly in flow {} instead.
When Type Errors Usually Mean A Boundary Problem
If the compiler error mentions one of these shapes, check the boundary first:
Result<...>Async<...>Async<Result<...>>Task<...>Task<Result<...>>Flow<...>
Most fixes are one of:
- add a type annotation to disambiguate
let!overloads - derive a smaller local environment with
localEnv - use
Guard.OforGuard.MapErrorto bridge existing error-bearing sources - move back to plain Result until the real workflow boundary appears
Next
Read docs/GETTING_STARTED.md for the workflow overview,
docs/TASK_ASYNC_INTEROP.md for the binding surface,
and examples/FsFlow.MaintenanceExamples/Program.fs
for runnable versions of these shapes.