dotnet/wpf · error · InvalidOperationException
SR.Enumerator_NotStarted
Error message
SR.Enumerator_NotStarted
What it means
FreezableCollection<T>.Enumerator.Current throws InvalidOperationException(SR.Enumerator_NotStarted) when accessed before the first MoveNext call (_index == -1). There is no current element yet, so reading Current is undefined and rejected.
Solutions
- Call MoveNext() at least once and check it returned true before reading Current.
- Prefer foreach, which guarantees Current is only read after a successful MoveNext.
- Initialize/prime the enumerator before exposing it to code that reads Current.
Example fix
// before
var e = collection.GetEnumerator();
var first = e.Current; // throws
// after
var e = collection.GetEnumerator();
if (e.MoveNext()) { var first = e.Current; } Defensive patterns
Strategy: validation
Validate before calling
if (!started) throw new InvalidOperationException("Call MoveNext() before reading Current."); Type guard
bool TryGetFirst<T>(IEnumerator<T> e, out T value) { if (e.MoveNext()) { value = e.Current; return true; } value = default; return false; } Try / catch
try { var cur = e.Current; }
catch (InvalidOperationException) { /* enumerator not started; call MoveNext first */ } Prevention
- Always check MoveNext() returned true before reading Current
- Prefer foreach which handles this ordering
- Never read Current immediately after GetEnumerator()
When it happens
Trigger: Reading enumerator.Current (or using foreach's variable) before calling MoveNext, e.g. accessing Current immediately after GetEnumerator() or accessing the loop variable before the first iteration in hand-rolled loops.
Common situations: Hand-rolled enumeration code that reads Current before advancing, refactored foreach loops where an early 'peek' at Current was added, storing the enumerator and reading Current later before starting.
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.Enumerator_NotStarted
- SR.Enumerator_ReachedEnd
- SR.Enumerator_ReachedEnd
- SR.Enumerator_NotStarted
- SR.Enumerator_NotStarted
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/947ea3940dcf0d37.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/FreezableCollection.cs:1074
/// <summary>
/// Current element
///
/// The behavior of IEnumerable<T>.Current is undefined
/// before the first MoveNext and after we have walked
/// off the end of the list. However, the IEnumerable.Current
/// contract requires that we throw exceptions
/// </summary>
public T Current
{
get
{
if (_index > -1)
{
return _current;
}
else if (_index == -1)
{
throw new InvalidOperationException(SR.Enumerator_NotStarted);
}
else
{
Debug.Assert(_index == -2, "expected -2, got " + _index + "\n");
throw new InvalidOperationException(SR.Enumerator_ReachedEnd);
}
}
}
#endregion
#region Data
private T _current;
private FreezableCollection<T> _list;
private uint _version;
private int _index;
#endregion
}View on GitHub (pinned to 81131a70a4)