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
- Only access Current inside the loop while MoveNext() returns true.
- Capture the last value inside the loop instead of reading Current afterwards.
- 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
- Capture Current inside the MoveNext loop
- Don't cache and read Current after enumeration ends
- Call Reset or acquire a new enumerator for reuse
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
- SR.EnumeratorNotStarted
- InvalidOperationException
- SR.Enumerator_CollectionChanged
- SR.Enumerator_NotStarted
- SR.Enumerator_NotStarted
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)