louthy/language-ext · error · InvalidOperationException
Nil iterator has no head
Error message
Nil iterator has no head
What it means
This InvalidOperationException fires when Head is read on the Nil (empty) case of IteratorAsync<A>. Nil represents the end of an async sequence and has no first element, so the Head property is a hard guard with no meaningful value to return. It indicates the consumer did not check IsNil/emptiness before requesting the head of the sequence.
Solutions
- Await IsEmpty before awaiting Head.
- Prefer AsEnumerable()/AsAsyncEnumerable enumeration or FoldAsync-style combinators over manual Head/Tail stepping.
- Guard: `var head = await it.IsEmpty ? Prelude.None : Prelude.Some(await it.Head);`
Example fix
// before var head = await it.Head; // after var head = await it.IsEmpty ? Prelude.None : Prelude.Some(await it.Head);
Defensive patterns
Strategy: validation
Validate before calling
if (await it.IsEmpty) throw new InvalidOperationException("Cannot take Head of an empty async iterator");
var head = await it.Head; Type guard
static async ValueTask<Option<A>> TryHead<A>(IteratorAsync<A> it) => await it.IsEmpty ? Prelude.None : Prelude.Some(await it.Head);
Try / catch
try { head = await it.Head; }
catch (InvalidOperationException) { head = Option<A>.None; } Prevention
- Await IsEmpty before every Head access in async Head/Tail loops.
- Use AsEnumerable/await-foreach instead of manual async traversal.
- Return Option<A>/Try monads from async head-extraction helpers.
- Port checks 1:1 when converting sync Iterator code to IteratorAsync.
When it happens
Trigger: Awaiting `.Head` on an IteratorAsync<A> in the Nil state — e.g. after consuming all elements via repeated Tail, or on the Default/Nil singleton.
Common situations: Manual async Head/Tail recursion that doesn't stop at the empty case; awaiting Head on a stream that produced zero elements (e.g. empty DB result); porting sync Iterator code that already guarded but the async port doesn't.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- Nil iterator has no head
- OperationCanceledException
- IndexOutOfRangeException
- AggregateException from collected inner errors
- Ord attribute should have a struct type that derives from…
AI-assisted analysis of louthy/language-ext@2f0e362824 (2026-09-15).
Data as JSON: /api/errors/bcad5e355649944c.
Report an issue: GitHub.
Appendix: source
Thrown at LanguageExt.Core/Immutable Collections/IteratorAsync/DSL/IteratorAsync.Nil.cs:22
namespace LanguageExt;
public abstract partial class IteratorAsync<A>
{
/// <summary>
/// Nil iterator case
///
/// The end of the sequence.
/// </summary>
public sealed class Nil : IteratorAsync<A>
{
public static readonly IteratorAsync<A> Default = new Nil();
/// <summary>
/// Head element
/// </summary>
public override ValueTask<A> Head =>
throw new InvalidOperationException("Nil iterator has no head");
/// <summary>
/// Tail of the sequence
/// </summary>
public override ValueTask<IteratorAsync<A>> Tail =>
new(this);
/// <summary>
/// Return true if there are no elements in the sequence.
/// </summary>
public override ValueTask<bool> IsEmpty =>
new(true);
/// <summary>
/// Clone the iterator so that we can consume it without having the head item referenced.
/// This will stop any GC pressure.
/// </summary>
public override IteratorAsync<A> Clone() =>View on GitHub (pinned to 2f0e362824)