louthy/language-ext · error · ArgumentNullException

ArgumentNullException

Error message

ArgumentNullException

What it means

LstInternal.SetItem(int index, A value) throws ArgumentNullException when the replacement value is null. Lst (the AVL-backed persistent list) forbids null elements, so even a value-replacement at a valid index must be non-null; this check runs before the index check.

Solutions

  1. Ensure the replacement value is non-null before calling SetItem.
  2. If the value may be null, wrap it in an Option<A> or a sentinel value rather than storing null.
  3. Fix the Func<V,V>/updater so it never returns null (use Option.Match with a fallback).
  4. Enable nullable reference types so null passing is caught at compile time.

Example fix

// before
var updated = lst.SetItem(0, user?.Name); // null if user null
// after
var name = user?.Name ?? throw new InvalidOperationException("user must have a name");
var updated = lst.SetItem(0, name);
Defensive patterns

Strategy: validation

Validate before calling

if (value is null)
    throw new ArgumentNullException(nameof(value));
var updated = lst.SetItem(index, value);

Type guard

static bool IsSettable<A>(A value) where A : class => value is not null;

Try / catch

try { lst = lst.SetItem(index, value); }
catch (ArgumentNullException ex) when (ex.ParamName == "value")
{
    // handle null replacement value
}

Prevention

When it happens

Trigger: Calling SetItem(index, null) — directly, or via a Func<A,A> updater that returns null (e.g. mapping an item to a null result) and then setting it back.

Common situations: Updater lambdas like x => x?.Child that can yield null; deserialized data containing nulls; nullable reference types disabled so the compiler does not warn about passing null.

Related errors


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

Appendix: source

Thrown at LanguageExt.Core/Immutable Collections/List/Internal/Lst.Internal.cs:282

        if (index < 0 || index >= Root.Count) throw new IndexOutOfRangeException();
        if (index + count > Root.Count) throw new IndexOutOfRangeException();

        var self = this;
        for (; count > 0; count--)
        {
            self = self.RemoveAt(index);
        }
        return self;
    }

    /// <summary>
    /// Set an item at the specified index
    /// </summary>
    [Pure]
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public LstInternal<A> SetItem(int index, A value)
    {
        if (isnull(value)) throw new ArgumentNullException(nameof(value));
        if (index < 0 || index >= Root.Count) throw new IndexOutOfRangeException();
        return new LstInternal<A>(ListModule.SetItem(Root, value, index));
    }

    [Pure]
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    IEnumerator IEnumerable.GetEnumerator() =>
        new ListEnumerator<A>(Root, false, 0);

    [Pure]
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    IEnumerator<A> IEnumerable<A>.GetEnumerator() =>
        new ListEnumerator<A>(Root, false, 0);

    [Pure]
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public Iterable<A> Skip(int amount)
    {

View on GitHub (pinned to 2f0e362824)