dotnet/wpf · error · InvalidOperationException
throw new…
Error message
throw new InvalidOperationException(SR.EnumeratorVersionChanged);
What it means
IndexedEnumerable's IEnumerator.Reset() requires the owning IndexedEnumerable to still reference a live enumerable (_enumerable != null). When the parent enumerable was replaced or cleared (e.g. the view re-created the IndexedEnumerable after a collection change), Reset() treats the enumerator as orphaned and throws InvalidOperationException with EnumeratorVersionChanged.
Solutions
- Discard the stale enumerator and request a new one via GetEnumerator() instead of calling Reset().
- Re-query the view/enumerable after any Refresh or rebind before resuming iteration.
- Restructure iteration into a method that creates a fresh enumerator on each pass.
- Catch InvalidOperationException and fall back to re-enumeration with a new enumerator.
Example fix
// before enumerator.Reset(); // stale after refresh // after enumerator = indexedEnumerable.GetEnumerator(); // fresh enumerator
Defensive patterns
Strategy: try-catch
Try / catch
try { enumerator.Reset(); }
catch (InvalidOperationException) { enumerator = enumerable.GetEnumerator(); } Prevention
- Treat enumerators as invalid after Refresh/rebind; create new ones.
- Avoid calling Reset() on WPF collection-view enumerators.
- Scope enumerators to a single iteration pass.
- Re-acquire enumerators after any ItemsSource change.
When it happens
Trigger: Calling IEnumerator.Reset() (explicit interface implementation) on an enumerator obtained from an IndexedEnumerable after the source enumerable was detached — typically following a collection Refresh or rebind that invalidated the enumerator.
Common situations: Holding an IEnumerator across a CollectionView.Refresh() or ItemsSource change and calling Reset() to restart iteration; long-lived enumerators stored in helper classes while the view rebinds.
Related errors
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/078b295782435b42.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Data/IndexedEnumerable.cs:722
//------------------------------------------------------
//
// Private Types
//
//------------------------------------------------------
private class FilteredEnumerator : IEnumerator, IDisposable
{
public FilteredEnumerator(IndexedEnumerable indexedEnumerable, IEnumerable enumerable, Predicate<object> filterCallback)
{
_enumerable = enumerable;
_enumerator = _enumerable.GetEnumerator();
_filterCallback = filterCallback;
_indexedEnumerable = indexedEnumerable;
}
void IEnumerator.Reset()
{
if (_indexedEnumerable._enumerable == null)
throw new InvalidOperationException(SR.EnumeratorVersionChanged);
Dispose();
_enumerator = _enumerable.GetEnumerator();
}
bool IEnumerator.MoveNext()
{
bool returnValue;
if (_indexedEnumerable._enumerable == null)
throw new InvalidOperationException(SR.EnumeratorVersionChanged);
if (_filterCallback == null)
{
returnValue = _enumerator.MoveNext();
}
else
{View on GitHub (pinned to 81131a70a4)