{"record":{"id":"33f67156bbd59f14","repo":"louthy/language-ext","slug":"list-is-empty","errorCode":null,"errorMessage":"List is empty","messagePattern":"List is empty","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"LanguageExt.Core/DataTypes/Patch/Patch.Internal.cs","lineNumber":42,"sourceCode":"        return (a1, c.Cons(c1));\n    }\n\n    public static (C, Seq<O>) leastChanges<OrdC, V, O, C>(PatchParams<V, O, C> p, SpanArray<V> ss, SpanArray<V> tt)\n        where OrdC : Ord<C>\n        where C : Monoid<C>\n    {\n        var rawChanges = rawChanges<OrdC, V, O, C>(p, ss, tt);\n        var changes    = rawChanges.Last;\n        var newlst     = changes.Map(pair => toSeq(pair.Item2.Somes().Reverse()));\n        return (changes.Item1, newlst);\n    }\n\n    static (int quot, int rem) quotRem(int x, int y) =>\n        (x / y, x % y);\n\n    static A minimumBy<A>(Func<A, A, int> compare, Lst<A> list) =>\n        list.Count == 0\n            ? throw new Exception(\"List is empty\")\n            : list.Fold(list[0], (x, y) => compare(x, y) > 0 ? y : x);\n\n    static SpanArray<A> constructN<A>(int n, Func<SpanArray<A>, A> f)\n    {\n        var vector = SpanArray<A>.New(n);\n        for (var i = 0; i < n; i++)\n        {\n            var slice = vector.Slice(0, i);\n            var x     = f(slice);\n            vector[i] = x;\n        }\n        return vector;\n    }\n\n    public static SpanArray<(C, Seq<Option<O>>)> rawChanges<OrdC, V, O, C>(PatchParams<V, O, C> p, SpanArray<V> src, SpanArray<V> dst)\n        where OrdC : Ord<C>\n        where C : Monoid<C>\n    {","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/louthy/language-ext/blob/2f0e3628242889774d4141960a35671a0280051f/LanguageExt.Core/DataTypes/Patch/Patch.Internal.cs#L24-L60","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Guard before calling: `if (list.Count == 0) return ...` or use a sensible default value for the empty case.","Skip patch computation entirely when either input collection is empty — the patch is trivially empty/replace-all.","Catch and map the generic exception to a domain error if you cannot pre-validate."],"exampleFix":"// before\nvar m = minimumBy(compare, list); // throws when list is empty\n\n// after\nvar m = list.Count == 0 ? Option<A>.None : minimumBy(compare, list);","handlingStrategy":"validation","validationCode":"if (list.Count == 0) return Option<A>.None; // or a default, before calling the diff/patch","typeGuard":null,"tryCatchPattern":"try { var m = minimumBy(compare, list); }\ncatch (Exception ex) when (ex.Message == \"List is empty\") { /* use default */ }","preventionTips":["Check collection emptiness before any Patch/diff computation.","Treat empty-vs-X diffs as trivial replace patches, skipping the algorithm.","Prefer Option-typed min helpers over throwing variants in your own code."],"tags":["patch","diff","empty-collection","csharp"],"backgroundTag":"empty-required-field","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"}