louthy/language-ext · error · IndexOutOfRangeException
IndexOutOfRangeException
Error message
IndexOutOfRangeException
What it means
LanguageExt's Seq.head lens throws IndexOutOfRangeException when the target Seq is empty. Lenses are total-style accessors but the head lens cannot produce a value for an empty sequence, so it throws instead of returning Option. The exception comes from the Get (or Set) lambda of the lens when la.IsEmpty is true.
Solutions
- Check la.IsEmpty (or la.Count == 0) before applying the head lens
- Use the headOrNone lens instead, which returns Option<A> and never throws
- Use Seq.head() / HeadOrNone() extension functions rather than the lens
- Wrap the lens application in try-catch for IndexOutOfRangeException if the empty case is expected
Example fix
// before var first = Seq.head.Get(mySeq); // after var first = mySeq.IsEmpty ? Option<A>.None : Seq.headOrNone.Get(mySeq);
Defensive patterns
Strategy: validation
Validate before calling
if (seq.IsEmpty) throw new InvalidOperationException("Cannot get head of empty Seq");
var first = Seq.head.Get(seq); Type guard
static bool HasHead<A>(Seq<A> s) => !s.IsEmpty;
Try / catch
try { first = Seq.head.Get(seq); }
catch (IndexOutOfRangeException) { first = default; /* empty seq */ } Prevention
- Prefer headOrNone lens over head for fallible access
- Check IsEmpty before any lens that requires elements
- Use HeadOrNone()/head() extension functions which return Option
When it happens
Trigger: Calling Seq<A>.head.Get() on an empty Seq, or head.Set() on an empty Seq. Any code path that applies the head lens without first checking IsEmpty.
Common situations: Taking the first element of a query/filter result that returned no items; processing a file or stream that produced zero lines; refactoring from List.First() to Seq.head without preserving the empty-collection check.
Related errors
- IndexOutOfRangeException
- InvalidOperationException
- NotSupportedException
- IndexOutOfRangeException
- IndexOutOfRangeException
AI-assisted analysis of louthy/language-ext@2f0e362824 (2026-09-15).
Data as JSON: /api/errors/8edfe54ab880a972.
Report an issue: GitHub.
Appendix: source
Thrown at LanguageExt.Core/Immutable Collections/Seq/Seq.cs:99
: Tail.IsEmpty
? Head.Value
: (Head.Value, Tail);
public void Deconstruct(out A head, out Seq<A> tail)
{
head = Head.IfNone(() => throw Exceptions.SequenceEmpty);
tail = Tail;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlySpan<A> AsSpan() =>
Value.AsSpan();
/// <summary>
/// Head lens
/// </summary>
public static Lens<Seq<A>, A> head => Lens<Seq<A>, A>.New(
Get: la => la.IsEmpty ? throw new IndexOutOfRangeException() : la[0],
Set: a => la => la.IsEmpty ? throw new IndexOutOfRangeException() : a.Cons(la.Tail)
);
/// <summary>
/// Head or none lens
/// </summary>
public static Lens<Seq<A>, Option<A>> headOrNone => Lens<Seq<A>, Option<A>>.New(
Get: la => la.Head,
Set: a => la => la.IsEmpty || a.IsNone ? la : a.Value.Cons(la.Tail!)!
);
/// <summary>
/// Tail lens
/// </summary>
public static Lens<Seq<A>, Seq<A>> tail => Lens<Seq<A>, Seq<A>>.New(
Get: la => la.IsEmpty ? Empty : la.Tail,
Set: a => la => la.IsEmpty ? a : ((A)la.Head).Cons(a)
);View on GitHub (pinned to 2f0e362824)