dotnet/wpf · error · InvalidOperationException

SR.EnumeratorReachedEnd

Error message

SR.EnumeratorReachedEnd

What it means

Grid's child enumerator's Current property throws InvalidOperationException (SR.EnumeratorReachedEnd) when Current is read after enumeration has finished (_currentEnumerator >= 3). Per the IEnumerator contract, Current is invalid once MoveNext() has returned false.

Solutions

  1. Only access Current inside the loop while MoveNext() returns true.
  2. Capture the last value inside the loop instead of reading Current afterwards.
  3. Call Reset() (or get a new enumerator) before re-enumerating an exhausted enumerator.

Example fix

// before
while (e.MoveNext()) { }
var last = e.Current; // InvalidOperationException
// after
object last = null;
while (e.MoveNext())
{
    last = e.Current;
}
Defensive patterns

Strategy: validation

Validate before calling

object last = null; while (e.MoveNext()) { last = e.Current; } // never read Current after loop

Type guard

bool CanReadCurrent(IEnumerator e) => e.MoveNext(); // re-check before each Current access

Try / catch

try { var cur = e.Current; }
catch (InvalidOperationException) { /* enumeration exhausted; capture values inside the loop instead */ }

Prevention

When it happens

Trigger: Calling MoveNext() until it returns false and then reading Current again; continuing to dereference a stored enumerator after the loop completed; reading Current after calling Reset-less exhausted enumeration across Grid children/row/column definition sets.

Common situations: Loop helpers that cache Current after the loop ends; retrying enumeration without calling Reset(); generic enumeration wrappers that read Current unconditionally after MoveNext fails.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/Grid.cs:3976

                    }
                    _currentEnumerator++;
                }
                return (false);
            }

            public Object Current
            {
                get
                {
                    if (_currentEnumerator == -1)
                    {
                        // IEnumerator.Current is documented to throw this exception
                        throw new InvalidOperationException(SR.EnumeratorNotStarted);
                    }
                    if (_currentEnumerator >= 3)
                    {
                        // IEnumerator.Current is documented to throw this exception
                        throw new InvalidOperationException(SR.EnumeratorReachedEnd);
                    }

                    //  assert below is not true anymore since UIElementCollection allowes for null children
                    //Debug.Assert(_currentChild != null);
                    return (_currentChild);
                }
            }

            public void Reset()
            {
                _currentEnumerator = -1;
                _currentChild = null;
                _enumerator0.Reset();
                _enumerator1.Reset();
                _enumerator2Index = 0;
            }

            private int _currentEnumerator;

View on GitHub (pinned to 81131a70a4)