dotnet/wpf · error · InvalidOperationException

SR.Enumerator_NotStarted

Error message

SR.Enumerator_NotStarted

What it means

The enumerator's Current property throws InvalidOperationException (SR.Enumerator_NotStarted) when accessed before the first MoveNext call (_index == -1). Current is only valid between a successful MoveNext and the end of enumeration.

Solutions

  1. Call MoveNext() and check it returned true before reading Current
  2. Restructure as foreach so the compiler manages the enumerator
  3. Guard reads with a position check (only read Current after a true MoveNext)

Example fix

// before
var e = collection.GetEnumerator();
var first = e.Current;
// after
var e = collection.GetEnumerator();
if (e.MoveNext()) { var first = e.Current; }
Defensive patterns

Strategy: validation

Validate before calling

// only read Current after a successful MoveNext
if (enumerator.MoveNext()) { var item = enumerator.Current; }

Try / catch

InvalidOperationException ex -> ensure a MoveNext() call precedes any Current read; restructure to foreach

Prevention

When it happens

Trigger: Reading Current immediately after GetEnumerator() without calling MoveNext first; accessing Current inside a finally/cleanup block before the loop ran.

Common situations: Manual enumerator code (while loops) forgetting the initial MoveNext; refactored foreach code that still touches enumerator.Current; generic enumerator wrappers that read Current unconditionally.

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


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/5632843339d047c0. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Generated/TextDecorationCollection.cs:840

            /// <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 TextDecoration 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 TextDecoration _current;
            private TextDecorationCollection _list;
            private uint _version;
            private int _index;
            #endregion
        }

View on GitHub (pinned to 81131a70a4)