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
- Only read Current after a MoveNext() that returned true (or inside foreach)
- Re-acquire GetEnumerator() instead of reusing a spent enumerator
- Replace manual enumerator code with foreach or LINQ (ToList, FirstOrDefault, etc.)
- 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
- Only access Current after a successful MoveNext
- Use foreach instead of manual enumerator code
- Never reuse an enumerator after it has been exhausted; get a new one
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
- SR.Enumerator_CollectionChanged
- SR.Enumerator_NotStarted
- SR.Enumerator_NotStarted
- SR.Enumerator_NotStarted
- SR.Enumerator_ReachedEnd
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)