dotnet/wpf · error · InvalidOperationException

SR.EnumeratorCollectionDisposed

Error message

SR.EnumeratorCollectionDisposed

What it means

The enumerator was invalidated because the underlying collection state is gone (_currentElement == null), which happens after the collection was disposed/cleared out from under the enumerator. PrivateValidate also throws EnumeratorVersionChanged if the collection was merely modified.

Solutions

  1. Re-acquire the enumerator via GetEnumerator() after the collection changes
  2. Do not cache enumerators across collection mutations
  3. Enumerate a snapshot (e.g. grid.ColumnDefinitions.ToArray()) if the collection may change

Example fix

// before
_cachedEnumerator = grid.ColumnDefinitions.GetEnumerator();
...
while (_cachedEnumerator.MoveNext()) { }
// after
foreach (var col in grid.ColumnDefinitions.ToArray()) { }
Defensive patterns

Strategy: try-catch

Validate before calling

var snapshot = grid.ColumnDefinitions.ToArray(); foreach (var col in snapshot) { }

Try / catch

try { while (e.MoveNext()) { } } catch (InvalidOperationException) { e = grid.ColumnDefinitions.GetEnumerator(); }

Prevention

When it happens

Trigger: Calling MoveNext() or Reset() on an enumerator after its owning ColumnDefinitionCollection has been disposed/invalidated (e.g. the Grid tore down its definitions).

Common situations: Holding an enumerator across a Grid teardown; long-lived enumerators cached in fields while the collection is reset; enumerating while the collection is cleared on another thread.

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/77544e2b214ffed3. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/ColumnDefinition.cs:920

            /// <summary>
            ///     <see cref="IDisposable.Dispose"/>
            /// </summary>
            public void Dispose()
            {
                _currentElement = null;
            }

            /// <summary>
            ///     Validates that
            ///     enumerator is not disposed;
            ///     enumerator is still in sync with collection;
            /// </summary>
            private void PrivateValidate()
            {
                if (_currentElement == null)
                {
                    throw new InvalidOperationException(SR.EnumeratorCollectionDisposed);
                }
                if (_version != _collection._version)
                {
                    throw new InvalidOperationException(SR.EnumeratorVersionChanged);
                }
            }

            private ColumnDefinitionCollection _collection;              //  the collection to be enumerated
            private int _index;                         //  current element index
            private int _version;                       //  the snapshot of collection's version at the time of creation
            private object _currentElement;             //  multipurpose:
                                                        //  points to the collection object when enumerator is either before start or after end
                                                        //  points to the current element while in the process of enumeration
                                                        //  is null if disposed
        }

        #endregion Private Structures Classes
    }

View on GitHub (pinned to 81131a70a4)