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

  1. Call MoveNext() (and check it returns true) before reading Current.
  2. Prefer foreach, which handles cursor state automatically.
  3. 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

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


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&lt;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)