louthy/language-ext · warning · OperationCanceledException
OperationCanceledException
Error message
OperationCanceledException
What it means
Iterable.AsEnumerableIO returns an IO-wrapped IEnumerable whose iterator checks env.Token before yielding each Prefix element; when cancellation is requested it throws OperationCanceledException. This is cooperative cancellation: the enumeration aborts as soon as the token from EnvIO is signaled, so the consumer must be prepared for the sequence to terminate via this exception rather than completing.
Solutions
- Catch OperationCanceledException around enumeration and treat it as expected cancellation, not a failure.
- Check env.Token.IsCancellationRequested before/while consuming and stop gracefully.
- Use IO.cancel or run the whole IO under the caller's token semantics instead of mixing tokens.
- If cancellation is not desired, run with a CancellationToken.None-based EnvIO.
Example fix
// before
foreach (var x in iterable.AsEnumerableIO().Run(env)) Process(x); // throws on cancel
// after
try
{
foreach (var x in iterable.AsEnumerableIO().Run(env)) Process(x);
}
catch (OperationCanceledException) when (env.Token.IsCancellationRequested)
{
// graceful cancellation
} Defensive patterns
Strategy: try-catch
Validate before calling
if (env.Token.IsCancellationRequested) return; // stop before enumerating
Type guard
static bool CanEnumerate(EnvIO env) => !env.Token.IsCancellationRequested;
Try / catch
try { foreach (var x in seq) { ... } }
catch (OperationCanceledException) when (env.Token.IsCancellationRequested) { /* expected cancellation */ } Prevention
- Check the token before and during enumeration.
- Always filter OperationCanceledException with a when(token.IsCancellationRequested) clause.
- Treat partial consumption as the expected contract for cancellable enumerables.
- Match the EnvIO token to the desired operation lifetime.
When it happens
Trigger: Enumerating the IEnumerable returned by iterable.AsEnumerableIO().Run(...) after (or while) the EnvIO CancellationToken is cancelled; consuming the sequence lazily after a timeout or shutdown signal fires.
Common situations: Host cancellation/shutdown mid-enumeration, ASP.NET request abort tokens flowing into EnvIO, or a CancellationTokenSource cancelled because a timeout elapsed while the consumer was still pulling items.
Related errors
- OperationCanceledException
- OperationCanceledException
- OperationCanceledException
- OperationCanceledException
- OperationCanceledException
AI-assisted analysis of louthy/language-ext@2f0e362824 (2026-09-15).
Data as JSON: /api/errors/6732fb7ab97ef62d.
Report an issue: GitHub.
Appendix: source
Thrown at LanguageExt.Core/Immutable Collections/Iterable/DSL/Iterable.Add.cs:29
Source.IsAsync;
public override IO<int> CountIO() =>
Source.CountIO().Map(c => Prefix.Count + c + Postfix.Count);
public override Iterable<A> Add(A item) =>
new IterableAdd<A>(Prefix, Source, (SeqStrict<A>)Postfix.Add(item));
public override Iterable<A> Cons(A item) =>
new IterableAdd<A>((SeqStrict<A>)Prefix.Cons(item), Source, Postfix);
public override IO<IEnumerable<A>> AsEnumerableIO()
{
return IO.lift(go);
IEnumerable<A> go(EnvIO env)
{
foreach (var x in Prefix)
{
if (env.Token.IsCancellationRequested) throw new OperationCanceledException();
yield return x;
}
foreach (var x in Source.AsEnumerable(env.Token))
{
if(env.Token.IsCancellationRequested) throw new OperationCanceledException();
yield return x;
}
foreach (var x in Postfix)
{
if (env.Token.IsCancellationRequested) throw new OperationCanceledException();
yield return x;
}
}
}
public override IO<IAsyncEnumerable<A>> AsAsyncEnumerableIO()View on GitHub (pinned to 2f0e362824)