AvaloniaUI/Avalonia · error · InvalidOperationException

Collection was modified during enumeration.

Error message

Collection was modified during enumeration.

What it means

InvalidOperationException thrown by the PooledStack<T> enumerator's MoveNext when the stack's version stamp differs from the one captured at enumerator creation (`_version != _stack._version`). PooledStack bumps _version on every Push/Pop/Clear/return, so any structural change during enumeration invalidates the enumerator and this guard aborts iteration rather than yielding stale or corrupt data.

Source

Thrown at src/Avalonia.Base/Collections/Pooled/PooledStack.cs:647

            internal Enumerator(PooledStack<T> stack)
            {
                _stack = stack;
                _version = stack._version;
                _index = -2;
                _currentElement = default;
            }

            public void Dispose()
            {
                _index = -1;
            }

            public bool MoveNext()
            {
                bool retval;
                if (_version != _stack._version)
                    throw new InvalidOperationException("Collection was modified during enumeration.");
                if (_index == -2)
                {  // First call to enumerator.
                    _index = _stack._size - 1;
                    retval = (_index >= 0);
                    if (retval)
                        _currentElement = _stack._array[_index];
                    return retval;
                }
                if (_index == -1)
                {  // End of enumeration.
                    return false;
                }

                retval = (--_index >= 0);
                if (retval)
                    _currentElement = _stack._array[_index];
                else
                    _currentElement = default;

View on GitHub (pinned to 11c5427268)

Solutions

  1. Take a snapshot before iterating: `foreach (var x in stack.ToArray())`.
  2. Do not mutate the stack inside the loop; collect changes and apply them after the enumeration completes.
  3. Use a lock or copy for concurrent access.

Example fix

// before
foreach (var item in stack)
    stack.Pop(); // mutates during enumeration

// after
foreach (var item in stack.ToArray())
    stack.Pop();
Defensive patterns

Strategy: validation

Validate before calling

foreach (var item in stack.ToArray()) // iterate a snapshot
    Process(item); // safe to Push/Pop here

Prevention

When it happens

Trigger: Calling Push/Pop/Clear/Trim on a PooledStack while a `foreach` or manual MoveNext loop over that same stack is in progress; modifying the stack from inside the loop body.

Common situations: Removing/adding items inside a foreach; reentrancy where an event handler mutates the stack during enumeration; iterating a stack that another thread mutates.

Related errors


AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13). Data as JSON: /api/errors/a61608da461f4688. Report an issue: GitHub.