dotnet/wpf · error · InvalidOperationException

SR.Enumerator_CollectionChanged

Error message

SR.Enumerator_CollectionChanged

What it means

PathSegmentCollection's Enumerator.MoveNext throws Enumerator_CollectionChanged (InvalidOperationException) when the underlying collection's version changed after the enumerator was created. The enumerator is fail-fast: any Add, Remove, Insert, or Clear between MoveNext calls invalidates it.

Solutions

  1. Do not modify the collection while enumerating; collect pending changes in a separate list and apply after the loop.
  2. Iterate over a snapshot: foreach (var s in collection.ToArray()).
  3. Use a for loop over indices if you must mutate during traversal (and adjust the index accordingly).
  4. Synchronize access across threads (lock or freeze the collection for cross-thread reads).

Example fix

// before
foreach (var seg in segments) { if (bad(seg)) segments.Remove(seg); }
// after
foreach (var seg in segments.ToArray()) { if (bad(seg)) segments.Remove(seg); }
Defensive patterns

Strategy: try-catch

Validate before calling

// snapshot before iterating
var snapshot = segments.ToArray();

Try / catch

try { foreach (var s in segments) { Process(s); } }
catch (InvalidOperationException ex) when (ex.Message.Contains("collection")) { /* re-enumerate after mutations settle */ }

Prevention

When it happens

Trigger: Modifying the PathSegmentCollection (Add/Remove/Insert/Clear, or changing a segment that raises collection change) while a foreach or explicit Enumerator is iterating it.

Common situations: Mutating path segments inside a foreach loop, a property-changed or rendering callback altering the collection during enumeration, or multi-threaded access where one thread enumerates while another modifies.

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


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/4c40dfcb126017a8. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Generated/PathSegmentCollection.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)