dotnet/wpf · error · InvalidOperationException
SR.Enumerator_CollectionChanged
Error message
SR.Enumerator_CollectionChanged
What it means
The DoubleCollection enumerator's MoveNext validates that the collection's version stamp matches the version captured when enumeration began. If the collection was modified (Add/Remove/Insert/Clear) after the enumerator was created, it throws InvalidOperationException with SR.Enumerator_CollectionChanged. This protects callers from undefined iteration over a mutated list.
Solutions
- Materialize the collection first (e.g. foreach over coll.ToArray() or ToList()) when you must modify during iteration.
- Collect items to remove in a separate list, then apply removals after the loop ends.
- Guard concurrent access with a lock so no mutation occurs while an enumerator is active.
Example fix
// before
foreach (double d in coll) { if (d < 0) coll.Remove(d); } // InvalidOperationException
// after
foreach (double d in coll.ToArray()) { if (d < 0) coll.Remove(d); } Defensive patterns
Strategy: validation
Validate before calling
// snapshot before iterating to survive mutations var snapshot = coll.ToArray();
Try / catch
try
{
foreach (double d in snapshot) { /* mutate coll freely */ }
}
catch (InvalidOperationException ex) when (ex.Message.Contains("Enumerator_CollectionChanged"))
{ /* re-enumerate over a fresh snapshot */ } Prevention
- Never Add/Remove on a collection inside its own foreach.
- Iterate over a ToArray()/ToList() snapshot when mutation is required.
- Synchronize collection access across threads with a lock.
- Batch modifications outside of enumeration loops.
When it happens
Trigger: Creating an enumerator (foreach over a DoubleCollection), then calling Add/Remove/Insert/Clear on the collection, then continuing MoveNext — the next MoveNext call after the change throws.
Common situations: Modifying a DoubleCollection inside a foreach loop over it (e.g. removing points while iterating animation keyframes); a callback or event handler mutating the collection during enumeration; multi-threaded updates without synchronization.
Related errors
- InvalidOperationException
- SR.Enumerator_CollectionChanged
- SR.Enumerator_CollectionChanged
- SR.Enumerator_CollectionChanged
- SR.Enumerator_CollectionChanged
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/cfabb2fc228268e8.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Generated/DoubleCollection.cs:815
{
_list.ReadPreamble();
if (_version == _list._version)
{
if (_index > -2 && _index < _list._collection.Count - 1)
{
_current = _list._collection[++_index];
return true;
}
else
{
_index = -2; // -2 indicates "past the end"
return false;
}
}
else
{
throw new InvalidOperationException(SR.Enumerator_CollectionChanged);
}
}
/// <summary>
/// Sets the enumerator to its initial position, which is before the
/// first element in the collection.
/// </summary>
public void Reset()
{
_list.ReadPreamble();
if (_version == _list._version)
{
_index = -1;
}
else
{
throw new InvalidOperationException(SR.Enumerator_CollectionChanged);View on GitHub (pinned to 81131a70a4)