{"record":{"id":"bcad5e355649944c","repo":"louthy/language-ext","slug":"nil-iterator-has-no-head-iteratorasync","errorCode":null,"errorMessage":"Nil iterator has no head","messagePattern":"Nil iterator has no head","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"LanguageExt.Core/Immutable Collections/IteratorAsync/DSL/IteratorAsync.Nil.cs","lineNumber":22,"sourceCode":"\nnamespace LanguageExt;\n\npublic abstract partial class IteratorAsync<A>\n{\n    /// <summary>\n    /// Nil iterator case\n    ///\n    /// The end of the sequence.\n    /// </summary>\n    public sealed class Nil : IteratorAsync<A>\n    {\n        public static readonly IteratorAsync<A> Default = new Nil();\n\n        /// <summary>\n        /// Head element\n        /// </summary>\n        public override ValueTask<A> Head =>\n            throw new InvalidOperationException(\"Nil iterator has no head\");\n\n        /// <summary>\n        /// Tail of the sequence\n        /// </summary>\n        public override ValueTask<IteratorAsync<A>> Tail =>\n            new(this);\n\n        /// <summary>\n        /// Return true if there are no elements in the sequence.\n        /// </summary>\n        public override ValueTask<bool> IsEmpty =>\n            new(true);\n\n        /// <summary>\n        /// Clone the iterator so that we can consume it without having the head item referenced.\n        /// This will stop any GC pressure.\n        /// </summary>\n        public override IteratorAsync<A> Clone() =>","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/louthy/language-ext/blob/2f0e3628242889774d4141960a35671a0280051f/LanguageExt.Core/Immutable Collections/IteratorAsync/DSL/IteratorAsync.Nil.cs#L4-L40","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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);`"],"exampleFix":"// before\nvar head = await it.Head;\n// after\nvar head = await it.IsEmpty ? Prelude.None : Prelude.Some(await it.Head);","handlingStrategy":"validation","validationCode":"if (await it.IsEmpty) throw new InvalidOperationException(\"Cannot take Head of an empty async iterator\");\nvar head = await it.Head;","typeGuard":"static async ValueTask<Option<A>> TryHead<A>(IteratorAsync<A> it) => await it.IsEmpty ? Prelude.None : Prelude.Some(await it.Head);","tryCatchPattern":"try { head = await it.Head; }\ncatch (InvalidOperationException) { head = Option<A>.None; }","preventionTips":["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."],"tags":["csharp","languageext","empty-sequence","async","iterator"],"backgroundTag":"empty-result-set","analyzedSha":"2f0e3628242889774d4141960a35671a0280051f","analyzedAt":"2026-09-15T03:31:55.716Z","contentChangedAt":"2026-09-15T03:31:55.716Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}