dotnet/wpf · error · InvalidOperationException
SR.Enumerator_CollectionChanged
Error message
SR.Enumerator_CollectionChanged
What it means
The GeneralTransform3DCollection enumerator is version-checked: MoveNext throws InvalidOperationException (Enumerator_CollectionChanged) if the collection's version differs from the version captured when enumeration started. Any add, remove, or structural change during iteration invalidates the enumerator.
Solutions
- Iterate a snapshot: foreach (var t in collection.ToArray()) so mutations do not affect the loop.
- Collect items to remove in a list, then apply removals after the loop.
- Use a reverse for-loop over indices when removing by index.
Example fix
// before
foreach (var t in collection)
if (ShouldRemove(t)) collection.Remove(t);
// after
foreach (var t in collection.ToArray())
if (ShouldRemove(t)) collection.Remove(t); Defensive patterns
Strategy: fallback
Validate before calling
// snapshot before iterating var snapshot = collection.ToArray();
Try / catch
try
{
foreach (var t in collection) { /* ... */ }
}
catch (InvalidOperationException ex) when (ex.Message.Contains("changed"))
{
foreach (var t in collection.ToArray()) { /* retry on snapshot */ }
} Prevention
- Never mutate the collection inside foreach over it
- Iterate collection.ToArray() when mutations are possible
- Buffer removals and apply them after the loop
- Marshal cross-thread mutations to the UI thread
When it happens
Trigger: Calling Add/Insert/Remove/RemoveAt/Clear on the GeneralTransform3DCollection inside a foreach loop or between MoveNext calls.
Common situations: Removing transforms while iterating to 'clean up'; adding a transform inside an iteration based on a condition; collection mutated on another thread or via data binding during iteration.
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/2b15ed191d2b7a08.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media3D/Generated/GeneralTransform3DCollection.cs:795
{
_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)