dotnet/wpf · error · InvalidOperationException
SR.Enumerator_CollectionChanged
Error message
SR.Enumerator_CollectionChanged
What it means
TextEffectCollection's enumerator throws InvalidOperationException(Enumerator_CollectionChanged) in MoveNext when the collection's version changed after the enumerator was created. WPF collections use a version stamp to detect modification during enumeration and fail fast instead of returning inconsistent data.
Solutions
- Collect the items into a snapshot array/List first, then iterate and modify safely
- Move collection mutations outside the foreach loop
- Use a for loop over an index against a snapshot copy
Example fix
// before
foreach (var e in collection)
{
if (e.ShouldRemove) collection.Remove(e); // throws
}
// after
foreach (var e in collection.ToArray())
{
if (e.ShouldRemove) collection.Remove(e);
} Defensive patterns
Strategy: try-catch
Validate before calling
// snapshot before iterating var snapshot = collection.ToArray();
Try / catch
try { foreach (var e in snapshot) { /* mutate collection here safely */ } }
catch (InvalidOperationException ex) when (ex.Message.Contains("changed"))
{ /* restart enumeration with a fresh snapshot */ } Prevention
- Never Add/Remove/Clear during foreach over the same collection
- Iterate over collection.ToArray() when mutation is needed
- Avoid mutating the collection from event handlers fired during enumeration
- If multithreaded, guard mutations with a lock
When it happens
Trigger: Calling MoveNext after the collection was modified (Add/Remove/Insert/Clear) since GetEnumerator was called — e.g. adding an item inside a foreach over the collection.
Common situations: Removing an effect while iterating; modifying the collection from a PropertyChanged or render callback during enumeration; cross-thread mutation.
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_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/4a6268d57d8a1193.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Generated/TextEffectCollection.cs:797
{
_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)