AvaloniaUI/Avalonia · error · InvalidOperationException

Collection was modified during enumeration.

Error message

Collection was modified during enumeration.

What it means

Centralized ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion throws InvalidOperationException "Collection was modified during enumeration." It is actively used by PooledList<T>: in ForEach (after the loop if the version changed), in Enumerator.MoveNextRare, and in Enumerator.Reset — all triggered when PooledList's _version changed since the enumerator/action captured it. It is the canonical fail-fast for concurrent/recursive mutation during enumeration.

Source

Thrown at src/Avalonia.Base/Collections/Pooled/ThrowHelper.cs:306

            throw new InvalidOperationException("Enumeration has not started.");
        }

        [DoesNotReturn]
        internal static void ThrowInvalidOperationException_InvalidOperation_EnumEnded()
        {
            throw new InvalidOperationException("Enumeration has ended.");
        }

        [DoesNotReturn]
        internal static void ThrowInvalidOperationException_EnumCurrent(int index)
        {
            throw GetInvalidOperationException_EnumCurrent(index);
        }

        [DoesNotReturn]
        internal static void ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion()
        {
            throw new InvalidOperationException("Collection was modified during enumeration.");
        }

        [DoesNotReturn]
        internal static void ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen()
        {
            throw new InvalidOperationException("Invalid enumerator state: enumeration cannot proceed.");
        }

        [DoesNotReturn]
        internal static void ThrowInvalidOperationException_InvalidOperation_NoValue()
        {
            throw new InvalidOperationException("No value provided.");
        }

        [DoesNotReturn]
        internal static void ThrowInvalidOperationException_ConcurrentOperationsNotSupported()
        {
            throw new InvalidOperationException("Concurrent operations are not supported.");

View on GitHub (pinned to 11c5427268)

Solutions

  1. Iterate over a snapshot: `foreach (var x in list.ToArray())` or `list.Span` copied out.
  2. Defer mutations: collect items to add/remove during the loop and apply them after.
  3. For ForEach, do not mutate the list inside the action; use a plain for loop with index bounds instead.

Example fix

// before
foreach (var item in list)
    list.Remove(item); // mutates during enumeration

// after
foreach (var item in list.ToArray())
    list.Remove(item);
Defensive patterns

Strategy: validation

Validate before calling

foreach (var item in list.ToArray()) // snapshot before mutating
    list.Remove(item);

Prevention

When it happens

Trigger: Adding/removing/clearing/sorting a PooledList while a foreach or manual MoveNext loop over it is live; calling Reset() after mutating; ForEach whose callback mutates the list.

Common situations: Mutating the list inside a foreach body; event reentrancy that adds/removes items; sorting or clearing during iteration; concurrent access from another thread.

Related errors


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