dotnet/reactive · error · ArgumentOutOfRangeException

nameof(index)

Error message

nameof(index)

What it means

Thrown by ElementAt(source, index) when index is negative. The operator throws ArgumentOutOfRangeException naming index because a negative position can never match an element. Unlike ElementAtOrDefault, ElementAt treats both a null source and a negative index as hard errors.

Solutions

  1. Validate index >= 0 before calling ElementAt
  2. Clamp negative computed values to 0 or skip the call when index < 0
  3. Use ElementAtOrDefault for callers that want a default instead of an exception for missing positions (still validate non-negative first)
  4. When the index comes from external input (config, CLI, HTTP), parse and range-check it explicitly

Example fix

// before
int idx = items.Length - 1 - offset; // can be -1
var item = AsyncObservable.ElementAt(source, idx); // throws when idx < 0
// after
int idx = items.Length - 1 - offset;
if (idx >= 0)
{
    var item = AsyncObservable.ElementAt(source, idx);
}
Defensive patterns

Strategy: validation

Validate before calling

if (index < 0) throw new InvalidOperationException("ElementAt requires a non-negative index");
var item = AsyncObservable.ElementAt(source, index);

Type guard

bool IsValidIndex(int i) => i >= 0;

Try / catch

try
{
    var item = AsyncObservable.ElementAt(source, index);
}
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "index")
{
    // negative index; fall back to a default value
    item = default;
}

Prevention

When it happens

Trigger: Calling ElementAt(source, -1) or with an index computed from an unseeded counter, a failed parse, or an off-by-one decrement that went below zero.

Common situations: User-supplied indices parsed from config or CLI without validation; loop variables decremented before the call; arithmetic on empty collections (last - 1) yielding -1.

Related errors


AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15). Data as JSON: /api/errors/632723b1aff8e3a0. Report an issue: GitHub.

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/ElementAt.cs:16

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT License.
// See the LICENSE file in the project root for more information. 

using System.Threading.Tasks;

namespace System.Reactive.Linq
{
    public partial class AsyncObservable
    {
        public static IAsyncObservable<TSource> ElementAt<TSource>(this IAsyncObservable<TSource> source, int index)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (index < 0)
                throw new ArgumentOutOfRangeException(nameof(index));

            return Create(
                source,
                index,
                static (source, index, observer) => source.SubscribeSafeAsync(AsyncObserver.ElementAt(observer, index)));
        }
    }

    public partial class AsyncObserver
    {
        public static IAsyncObserver<TSource> ElementAt<TSource>(IAsyncObserver<TSource> observer, int index)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));
            if (index < 0)
                throw new ArgumentOutOfRangeException(nameof(index));

            return Create<TSource>(

View on GitHub (pinned to 94b5d5ab91)