dotnet/wpf · error · InvalidOperationException
SR.Enumerator_NotStarted
Error message
SR.Enumerator_NotStarted
What it means
Accessing the enumerator's Current property before the first MoveNext call throws InvalidOperationException (SR.Enumerator_NotStarted). Internally _index == -1 means the cursor is still positioned before the first element, so there is no current item to return.
Solutions
- Call MoveNext() (and check it returns true) before reading Current.
- Prefer foreach, which handles cursor state automatically.
- Initialize the current value from MoveNext's result: if (e.MoveNext()) var item = e.Current;
Example fix
// before
var e = collection.GetEnumerator();
var first = e.Current; // not started
// after
var e = collection.GetEnumerator();
if (e.MoveNext()) { var first = e.Current; } Defensive patterns
Strategy: type-guard
Validate before calling
if (e.MoveNext()) { var item = e.Current; } Type guard
bool HasCurrent<T>(IEnumerator<T> e) => e is { }; // only after a successful MoveNext Try / catch
try { var item = e.Current; } catch (InvalidOperationException) { /* MoveNext not called yet */ } Prevention
- Always pair Current with a preceding successful MoveNext
- Prefer foreach/LINQ over manual enumerators
- Remember Current is undefined before the first MoveNext
When it happens
Trigger: Reading enumerator.Current immediately after GetEnumerator() without calling MoveNext().
Common situations: Hand-written enumerator loops that read Current before advancing; assuming Current defaults to the first element.
Related errors
- SR.Enumerator_CollectionChanged
- SR.Enumerator_NotStarted
- SR.Enumerator_NotStarted
- SR.Enumerator_NotStarted
- SR.Enumerator_NotStarted
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/2895b121c9769bf6.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media3D/Generated/Transform3DCollection.cs:882
/// <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 Transform3D 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 Transform3D _current;
private Transform3DCollection _list;
private uint _version;
private int _index;
#endregion
}View on GitHub (pinned to 81131a70a4)