dotnet/wpf · error · InvalidOperationException

SR.Enumerator_ReachedEnd

Error message

SR.Enumerator_ReachedEnd

What it means

Model3DCollection's enumerator Current property throws InvalidOperationException(SR.Enumerator_ReachedEnd) when Current is accessed after MoveNext has returned false (i.e. the enumerator position is past the end, _index == -2). The WPF generated collection enumerators enforce strict access ordering: Current is only valid while positioned on an element.

Solutions

  1. Read Current only inside the loop, immediately after MoveNext() returns true
  2. Call Reset() before reusing an enumerator, or simply create a new one via GetEnumerator()
  3. Prefer a foreach loop over manual MoveNext/Current code so the compiler enforces correct usage

Example fix

// before
var e = collection.GetEnumerator();
while (e.MoveNext()) { }
Console.WriteLine(e.Current); // throws
// after
foreach (Model3D m in collection)
    Console.WriteLine(m);
Defensive patterns

Strategy: try-catch

Validate before calling

bool canReadCurrent = enumeratorHasStarted && !enumeratorFinished; // track MoveNext results yourself

Type guard

bool CanReadCurrent(System.Collections.IEnumerator e, bool lastMoveNextResult) => lastMoveNextResult;

Try / catch

try { var cur = e.Current; }
catch (InvalidOperationException) { /* enumerator past end; re-enumerate */ e.Reset(); }

Prevention

When it happens

Trigger: Accessing the Current property after a foreach loop has completed, or after calling MoveNext() until it returns false and then reading Current without calling Reset().

Common situations: Reusing a single enumerator object across multiple passes; storing the enumerator and reading Current after loop exit; hand-rolled iterator loops that forget to Reset() before reuse.

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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media3D/Generated/Model3DCollection.cs:887

            /// off the end of the list. However, the IEnumerable.Current
            /// contract requires that we throw exceptions
            /// </summary>
            public Model3D 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 Model3D _current;
            private Model3DCollection _list;
            private uint _version;
            private int _index;
            #endregion
        }
        #endregion

        #region Constructors

        //------------------------------------------------------

View on GitHub (pinned to 81131a70a4)