dotnet/wpf · error · ArgumentOutOfRangeException

throw new ArgumentOutOfRangeException(nameof(index)); //…

Error message

throw new ArgumentOutOfRangeException(nameof(index)); // validating the index argument

What it means

IndexedEnumerable.GetItemAt(index) uses a live enumerator: it calls MoveNext 'index' times to reach the requested item. If the enumerator runs out before consuming 'index' moves (moveBy != 0 at the end), the index exceeds the number of available items and ArgumentOutOfRangeException is thrown for the 'index' parameter.

Solutions

  1. Check index against Count (or InternalCount) before calling GetItemAt.
  2. Re-create the IndexedEnumerable if the underlying collection changed size.
  3. Use TryGetItemAt-style logic by catching ArgumentOutOfRangeException if racing changes are expected.
  4. Clamp index to Count - 1.

Example fix

// before
var item = indexedEnumerable.GetItemAt(i);
// after
if (i < indexedEnumerable.Count)
    var item = indexedEnumerable.GetItemAt(i);
Defensive patterns

Strategy: validation

Validate before calling

if (index < 0 || index >= indexedEnumerable.Count)
    throw new ArgumentOutOfRangeException(nameof(index), "index exceeds available items");
var item = indexedEnumerable.GetItemAt(index);

Type guard

bool IsValidIndex(IndexedEnumerable e, int i) => i >= 0 && i < e.Count;

Try / catch

try { item = e.GetItemAt(i); }
catch (ArgumentOutOfRangeException) { item = null; /* index no longer valid */ }

Prevention

When it happens

Trigger: Calling IndexedEnumerable.GetItemAt(index) (public API) with index >= Count of the underlying enumerable, or with an index valid at construction but beyond the (possibly changed/shrunken) source.

Common situations: ItemsControl scrolling code asking for an item at a position that no longer exists after the source collection shrank; off-by-one loops using Count from a stale copy.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/71aa8cfa546930b1. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Data/IndexedEnumerable.cs:243

                    if (index == _cachedIndex)
                        return _cachedItem;
                }
                else
                {
                    // there are new enumerators, caches were cleared, recalculate moveBy
                    moveBy = index + 1; // force at least one MoveNext
                }

                // position enumerator at new index:
                while ((moveBy > 0) && _enumerator.MoveNext())
                {
                    moveBy--;
                }

                // moved beyond the end of the enumerator?
                if (moveBy != 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(index)); // validating the index argument
                }

                CacheCurrentItem(index, _enumerator.Current);
                return _cachedItem;
            }
        }

        /// <summary>
        /// The enumerable collection wrapped by this indexer.
        /// </summary>
        internal IEnumerable Enumerable
        {
            get { return _enumerable; }
        }

        /// <summary>
        /// The collection wrapped by this indexer.
        /// </summary>

View on GitHub (pinned to 81131a70a4)