dotnet/wpf · error · InvalidOperationException
SR.Enumerator_NotStarted
Error message
SR.Enumerator_NotStarted
What it means
The enumerator's Current property tracks position via _index: -1 means MoveNext() has never been called, so no current element exists and it throws InvalidOperationException(SR.Enumerator_NotStarted). .NET enumerators must be advanced before Current is valid; MaterialCollection implements this fail-fast behavior explicitly.
Solutions
- Call MoveNext() before reading Current: if (e.MoveNext()) { var m = e.Current; }
- Prefer foreach, which handles MoveNext/Current sequencing correctly.
- If you need the first element without an enumerator, use materials[0] after checking Count > 0.
Example fix
// before var e = materials.GetEnumerator(); var first = e.Current; // after var e = materials.GetEnumerator(); var first = e.MoveNext() ? e.Current : null;
Defensive patterns
Strategy: type-guard
Validate before calling
bool hasCurrent = enumerator.MoveNext(); // must be true before reading Current
Type guard
static bool TryPeekFirst<T>(IEnumerator<T> e, out T current) { if (e.MoveNext()) { current = e.Current; return true; } current = default; return false; } Try / catch
try { var m = e.Current; }
catch (InvalidOperationException) { /* enumerator not started; call MoveNext first */ } Prevention
- Always pair Current with a successful MoveNext()
- Prefer foreach over manual enumerator code
- Use the indexer (materials[0]) for direct first-element access
When it happens
Trigger: Reading enumerator.Current (or calling Current manually on IEnumerator) immediately after GetEnumerator() without a prior MoveNext(), e.g. var e = materials.GetEnumerator(); var m = e.Current;
Common situations: Hand-rolled iteration code that skips the initial MoveNext; code translated from languages where iterators point at the first element before advancing; peeking at the 'first' item directly.
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_NotStarted
- SR.Enumerator_NotStarted
- SR.Enumerator_ReachedEnd
- SR.Enumerator_ReachedEnd
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/9d3850f0469db852.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media3D/Generated/MaterialCollection.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 Material 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 Material _current;
private MaterialCollection _list;
private uint _version;
private int _index;
#endregion
}View on GitHub (pinned to 81131a70a4)