dotnet/wpf · error · InvalidOperationException

SR.Enumerator_NotStarted

Error message

SR.Enumerator_NotStarted

What it means

GeneralTransformCollection.Enumerator.Current throws this InvalidOperationException when accessed before enumeration has started (internal _index is still -1, i.e. MoveNext() has never been called or Reset() was just called). The non-generic IEnumerator.Current contract requires an exception in this state instead of returning an undefined value.

Solutions

  1. Call MoveNext() at least once and only read Current when it returns true.
  2. Prefer a foreach loop, which manages MoveNext/Current ordering correctly.
  3. If using Reset(), re-issue MoveNext() before touching Current.
  4. Capture the current item as the return of MoveNext-driven iteration into a local variable instead of re-reading Current later.

Example fix

// before
var e = collection.GetEnumerator();
var first = e.Current; // throws: not started

// 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 current = enumerator.Current; }

Type guard

static bool TryGetCurrent<T>(this IEnumerator<T> e, out T current) { if (e.MoveNext()) { current = e.Current; return true; } current = default; return false; }

Try / catch

try { var v = enumerator.Current; }
catch (InvalidOperationException) { /* enumerator not started: call MoveNext() first */ }

Prevention

When it happens

Trigger: Accessing Current (or the explicit IEnumerator.Current) on a fresh enumerator from GeneralTransformCollection.GetEnumerator() without calling MoveNext() first, or accessing it immediately after calling Reset().

Common situations: Hand-written enumerator loops that read e.Current before the first e.MoveNext(); Reset()-then-Current patterns ported from code that assumed Current returns the first element; generic reflection/serialization helpers that poke at 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/34aadaa2bc6e2f25. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Generated/GeneralTransformCollection.cs:849

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

View on GitHub (pinned to 81131a70a4)