louthy/language-ext · error · ArgumentOutOfRangeException

ArgumentOutOfRangeException

Error message

ArgumentOutOfRangeException

What it means

The internal Arr slice constructor validates the window bounds into the backing array: start must be >= 0 and start + length must not exceed value.Length, otherwise ArgumentOutOfRangeException is thrown. An Arr is a lightweight view (value, start, length) over an array, and invalid slicing parameters are rejected here.

Solutions

  1. Clamp arguments: Math.Max(0, start) and Math.Min(length, value.Length - start).
  2. Fix the slice arithmetic (verify start/length derive from the same source array).
  3. Use public Arr/Skip/Take APIs rather than the internal constructor so bounds are computed for you.

Example fix

// before
new Arr<int>(data, data.Length, count);
// after
var s = Math.Min(Math.Max(0, start), data.Length);
new Arr<int>(data, s, Math.Min(count, data.Length - s));
Defensive patterns

Strategy: validation

Validate before calling

if (start < 0 || start + length > value.Length) throw new ArgumentOutOfRangeException(nameof(start));

Type guard

static bool ValidSlice<A>(A[] v, int start, int length) => start >= 0 && start + length <= v.Length;

Try / catch

try { var arr = new Arr<int>(data, start, len); } catch (ArgumentOutOfRangeException) { /* bad slice bounds */ }

Prevention

When it happens

Trigger: Constructing Arr via the internal (A[], int, int) ctor with a negative start, or a start+length combination exceeding the source array length (e.g. Skip/Take computed from wrong indices).

Common situations: Off-by-one errors in slicing logic, using a count from another collection that is longer than the source, or passing the original array length as start while also passing a positive length.

Related errors


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

Appendix: source

Thrown at LanguageExt.Core/Immutable Collections/Arr/Arr.cs:94

    /// <summary>
    /// Ctor
    /// </summary>
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    internal Arr(A[] value)
    {
        hashCode = Atom(0);
        this.value = value;
        start = 0;
        length = value.Length;
    }

    /// <summary>
    /// Ctor
    /// </summary>
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    internal Arr(A[] value, int start, int length)
    {
        if(start < 0) throw new ArgumentOutOfRangeException(nameof(start));
        if(start + length > value.Length) throw new ArgumentOutOfRangeException(nameof(length));
        hashCode = Atom(0);
        this.value = value;
        this.start = start;
        this.length = length;
    }
    
    /// <summary>
    /// Create a readonly span of this array.  This doesn't do any copying, so it is very fast.   
    /// </summary>
    /// <param name="start">Offset from the beginning of the array</param>
    /// <param name="count">The number of items to take. This will be clamped
    /// to the maximum number of items available</param>
    /// <returns>A read-only span of values</returns>
    /// <exception cref="IndexOutOfRangeException">Thrown If the start index is outside the range of the array</exception>
    [Pure]
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public ReadOnlySpan<A> AsSpan() =>

View on GitHub (pinned to 2f0e362824)