louthy/language-ext · error · Exception

List is empty

Error message

List is empty

What it means

`Patch.minimumBy` computes the minimum element of an `Lst<A>` using a comparison function; since `Lst` has no built-in minimum, the helper throws a plain `Exception("List is empty")` when handed a zero-length list. It's a precondition of the diff/patch algorithm (`rawChanges` uses it to pick the minimum cell), so an empty list there means degenerate input.

Solutions

  1. Guard before calling: `if (list.Count == 0) return ...` or use a sensible default value for the empty case.
  2. Skip patch computation entirely when either input collection is empty — the patch is trivially empty/replace-all.
  3. Catch and map the generic exception to a domain error if you cannot pre-validate.

Example fix

// before
var m = minimumBy(compare, list); // throws when list is empty

// after
var m = list.Count == 0 ? Option<A>.None : minimumBy(compare, list);
Defensive patterns

Strategy: validation

Validate before calling

if (list.Count == 0) return Option<A>.None; // or a default, before calling the diff/patch

Try / catch

try { var m = minimumBy(compare, list); }
catch (Exception ex) when (ex.Message == "List is empty") { /* use default */ }

Prevention

When it happens

Trigger: Calling the patch/diff machinery (`Patch`, `rawChanges` path) with an empty sequence, or invoking `minimumBy` on an empty `Lst<A>` — e.g. diffing two empty-or-degenerate collections in a way that produces an empty candidate list.

Common situations: Computing patches between empty collections; passing an empty list to a custom wrapper around internal patch helpers; algorithm edge cases where a caller didn't guard against empty input before diffing.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of louthy/language-ext@2f0e362824 (2026-09-15). Data as JSON: /api/errors/33f67156bbd59f14. Report an issue: GitHub.

Appendix: source

Thrown at LanguageExt.Core/DataTypes/Patch/Patch.Internal.cs:42

        return (a1, c.Cons(c1));
    }

    public static (C, Seq<O>) leastChanges<OrdC, V, O, C>(PatchParams<V, O, C> p, SpanArray<V> ss, SpanArray<V> tt)
        where OrdC : Ord<C>
        where C : Monoid<C>
    {
        var rawChanges = rawChanges<OrdC, V, O, C>(p, ss, tt);
        var changes    = rawChanges.Last;
        var newlst     = changes.Map(pair => toSeq(pair.Item2.Somes().Reverse()));
        return (changes.Item1, newlst);
    }

    static (int quot, int rem) quotRem(int x, int y) =>
        (x / y, x % y);

    static A minimumBy<A>(Func<A, A, int> compare, Lst<A> list) =>
        list.Count == 0
            ? throw new Exception("List is empty")
            : list.Fold(list[0], (x, y) => compare(x, y) > 0 ? y : x);

    static SpanArray<A> constructN<A>(int n, Func<SpanArray<A>, A> f)
    {
        var vector = SpanArray<A>.New(n);
        for (var i = 0; i < n; i++)
        {
            var slice = vector.Slice(0, i);
            var x     = f(slice);
            vector[i] = x;
        }
        return vector;
    }

    public static SpanArray<(C, Seq<Option<O>>)> rawChanges<OrdC, V, O, C>(PatchParams<V, O, C> p, SpanArray<V> src, SpanArray<V> dst)
        where OrdC : Ord<C>
        where C : Monoid<C>
    {

View on GitHub (pinned to 2f0e362824)