dotnet/wpf · error · InvalidOperationException

SR.Enumerator_NotStarted

Error message

SR.Enumerator_NotStarted

What it means

TransformCollection.Enumerator.Current throws InvalidOperationException with Enumerator_NotStarted when accessed before the first MoveNext() call. The enumerator's _index is still -1 (positioned before the first element), so there is no valid current item to return.

Solutions

  1. Always call MoveNext() (and check its true return value) before reading Current.
  2. Prefer foreach, which manages MoveNext/Current ordering automatically.
  3. If manual enumeration is required, initialize with `if (e.MoveNext()) { use e.Current; }`.
  4. Catch InvalidOperationException only as a last-resort guard around Current access.

Example fix

// before
var e = transformCollection.GetEnumerator();
var first = e.Current; // throws: not started
// after
var e = transformCollection.GetEnumerator();
if (e.MoveNext())
{
    var first = e.Current;
}
Defensive patterns

Strategy: validation

Validate before calling

if (transformCollection.Count > 0 && enumerator.MoveNext())
{
    var current = enumerator.Current; // safe
}

Type guard

static bool TryGetCurrent(TransformCollection c, out Transform current)
{
    using var e = c.GetEnumerator();
    if (e.MoveNext()) { current = e.Current; return true; }
    current = null; return false;
}

Try / catch

try
{
    var cur = enumerator.Current;
}
catch (InvalidOperationException)
{
    // MoveNext() was never called or enumeration ended; call MoveNext() first
}

Prevention

When it happens

Trigger: Accessing the Current property immediately after GetEnumerator() without calling MoveNext() first; e.g. `var e = collection.GetEnumerator(); var t = e.Current;`.

Common situations: Hand-written enumerator loops that forget the initial MoveNext(); code ported from COM-style iteration; LINQ-free manual enumeration where Current is read inside a condition evaluated before MoveNext.

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/a9d24468cae3b269. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Generated/TransformCollection.cs:884

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

View on GitHub (pinned to 81131a70a4)