dotnet/wpf · error · InvalidOperationException

SR.Timing_EnumeratorOutOfRange

Error message

SR.Timing_EnumeratorOutOfRange

What it means

The nested ClockEnumerator's IEnumerator<Clock>.Current throws InvalidOperationException with SR.Timing_EnumeratorOutOfRange when accessed while the enumerator is positioned before the first element (before any MoveNext) or after the last element (past the end). This is the standard CLR enumerator contract, surfaced with WPF's timing resource string.

Solutions

  1. Only read Current after a MoveNext() that returned true (or inside foreach)
  2. Re-acquire GetEnumerator() instead of reusing a spent enumerator
  3. Replace manual enumerator code with foreach or LINQ (ToList, FirstOrDefault, etc.)
  4. Check MoveNext's return value before every Current access

Example fix

// before
var e = clockCollection.GetEnumerator();
var c = e.Current; // InvalidOperationException
// after
var e = clockCollection.GetEnumerator();
if (e.MoveNext()) { var c = e.Current; }
Defensive patterns

Strategy: try-catch

Validate before calling

var e = clockCollection.GetEnumerator();
bool hasCurrent = e.MoveNext();
if (hasCurrent)
{
    var current = e.Current;
}

Type guard

bool TryCurrent(IEnumerator<Clock> e, out Clock current)
{
    current = null;
    return e != null && e.MoveNext() && (current = e.Current) != null;
}

Try / catch

try
{
    var current = enumerator.Current;
}
catch (InvalidOperationException)
{
    // enumerator not positioned on a valid element; reposition or re-enumerate
}

Prevention

When it happens

Trigger: Reading Current before calling MoveNext (e.g. var c = enumerator.Current;), continuing to read Current after MoveNext returned false, or a manual enumeration loop that reads Current unconditionally each iteration.

Common situations: Hand-rolled while-loop enumerations of clocks; using Current after a break without checking position; reusing a stale enumerator after the collection moved; calling Current in a finally/log block after enumeration finished.

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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Animation/TimelineClockCollection.cs:344

                // The enumerator doesn't do much, so we don't have to do
                // anything to dispose it.
            }

            #endregion // IDisposable interface

            #region IEnumerator interface

            /// <summary>
            /// Gets the current element in the collection.
            /// </summary>
            /// <value>
            /// The current element in the collection.
            /// </value>
            Clock IEnumerator<Clock>.Current
             {
                get
                {
                    throw new InvalidOperationException(SR.Timing_EnumeratorOutOfRange);
                }
            }

            #region IEnumerator Members

            object System.Collections.IEnumerator.Current
            {
                get
                {
                    return ((IEnumerator<Clock>)this).Current;
                }
            }

            void System.Collections.IEnumerator.Reset()
            {
                throw new NotImplementedException();
            }

View on GitHub (pinned to 81131a70a4)