AvaloniaUI/Avalonia · error · ArgumentOutOfRangeException

Specified argument was out of the range of valid values. (Pa

Error message

Specified argument was out of the range of valid values. (Parameter 'arrayIndex')

What it means

CompositeDisposable.CopyTo performs an upfront bounds check: if arrayIndex < 0 OR arrayIndex >= array.Length it throws ArgumentOutOfRangeException(nameof(arrayIndex)). This catches negative indices and an index at/past the end of a (possibly empty) array before copying.

Source

Thrown at src/Avalonia.Base/Reactive/CompositeDisposable.cs:301

    }

    /// <summary>
    /// Copies the disposables contained in the <see cref="CompositeDisposable"/> to an array, starting at a particular array index.
    /// </summary>
    /// <param name="array">Array to copy the contained disposables to.</param>
    /// <param name="arrayIndex">Target index at which to copy the first disposable of the group.</param>
    /// <exception cref="ArgumentNullException"><paramref name="array"/> is <c>null</c>.</exception>
    /// <exception cref="ArgumentOutOfRangeException"><paramref name="arrayIndex"/> is less than zero. -or - <paramref name="arrayIndex"/> is larger than or equal to the array length.</exception>
    public void CopyTo(IDisposable[] array, int arrayIndex)
    {
        if (array == null)
        {
            throw new ArgumentNullException(nameof(array));
        }

        if (arrayIndex < 0 || arrayIndex >= array.Length)
        {
            throw new ArgumentOutOfRangeException(nameof(arrayIndex));
        }

        lock (_gate)
        {
            // disposed composites are always empty
            if (_disposed)
            {
                return;
            }

            if (arrayIndex + _count > array.Length)
            {
                // there is not enough space beyond arrayIndex 
                // to accommodate all _count disposables in this composite
                throw new ArgumentOutOfRangeException(nameof(arrayIndex));
            }

            var i = arrayIndex;

View on GitHub (pinned to 11c5427268)

Solutions

  1. Validate arrayIndex is within [0, array.Length) and the array is large enough before calling.
  2. Allocate an array sized at least composite.Count and always start at index 0 unless you intentionally offset.
  3. Branch on array.Length == 0 to avoid the degenerate case.

Example fix

// before
composite.CopyTo(arr, arr.Length); // index >= length -> throws

// after
var arr = new IDisposable[composite.Count];
composite.CopyTo(arr, 0);
Defensive patterns

Strategy: validation

Validate before calling

if (array is null || arrayIndex < 0 || arrayIndex >= array.Length) return;
composite.CopyTo(array, arrayIndex);

Type guard

bool ValidIndex(IDisposable[] a, int i) => a is not null && i >= 0 && i < a.Length;

Prevention

When it happens

Trigger: Calling composite.CopyTo(arr, -1) or composite.CopyTo(arr, arr.Length), or CopyTo into an empty array with arrayIndex 0 (0 >= 0 length triggers it).

Common situations: Indexing into a zero-length array, or computing arrayIndex as a length that equals the array size, or passing a stale index after the array was resized down.

Related errors


AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13). Data as JSON: /api/errors/ed360a831eb789d1. Report an issue: GitHub.