dotnet/wpf · error · InvalidOperationException

SR.Enumerator_ReachedEnd

Error message

SR.Enumerator_ReachedEnd

What it means

The DoubleCollection enumerator's Current throws InvalidOperationException with SR.Enumerator_ReachedEnd when enumeration has completed (_index == -2, i.e. MoveNext returned false) and Current is accessed again. There is no current element once the enumerator is past the last item.

Solutions

  1. Read Current only inside the loop body while MoveNext() returns true.
  2. Store the needed element in a local variable during iteration for use afterwards.
  3. Create a new enumerator if you need to iterate again from the start.

Example fix

// before
while (e.MoveNext()) {}
var last = e.Current; // InvalidOperationException: Enumerator_ReachedEnd
// after
double last = double.NaN;
while (e.MoveNext()) { last = e.Current; }
Defensive patterns

Strategy: type-guard

Validate before calling

// only read Current when the last MoveNext() returned true
bool hasCurrent = e.MoveNext();
if (hasCurrent) { var d = e.Current; }

Try / catch

try { var d = e.Current; }
catch (InvalidOperationException ex) when (ex.Message.Contains("Enumerator_ReachedEnd"))
{ /* enumerator exhausted; recreate or use value saved in-loop */ }

Prevention

When it happens

Trigger: Iterating with MoveNext() until it returns false, then reading Current again; re-reading Current after a loop terminates; holding the enumerator after foreach completes and touching Current.

Common situations: Loop code that unconditionally reads Current after the while loop exits; caching the last-visited element via Current after iteration instead of storing it inside the loop.

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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Generated/DoubleCollection.cs:872

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

        #region Constructors

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

View on GitHub (pinned to 81131a70a4)