{"record":{"id":"a61608da461f4688","repo":"AvaloniaUI/Avalonia","slug":"collection-was-modified-during-enumeration","errorCode":null,"errorMessage":"Collection was modified during enumeration.","messagePattern":"Collection was modified during enumeration\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Avalonia.Base/Collections/Pooled/PooledStack.cs","lineNumber":647,"sourceCode":"\n            internal Enumerator(PooledStack<T> stack)\n            {\n                _stack = stack;\n                _version = stack._version;\n                _index = -2;\n                _currentElement = default;\n            }\n\n            public void Dispose()\n            {\n                _index = -1;\n            }\n\n            public bool MoveNext()\n            {\n                bool retval;\n                if (_version != _stack._version)\n                    throw new InvalidOperationException(\"Collection was modified during enumeration.\");\n                if (_index == -2)\n                {  // First call to enumerator.\n                    _index = _stack._size - 1;\n                    retval = (_index >= 0);\n                    if (retval)\n                        _currentElement = _stack._array[_index];\n                    return retval;\n                }\n                if (_index == -1)\n                {  // End of enumeration.\n                    return false;\n                }\n\n                retval = (--_index >= 0);\n                if (retval)\n                    _currentElement = _stack._array[_index];\n                else\n                    _currentElement = default;","sourceCodeStart":629,"sourceCodeEnd":665,"githubUrl":"https://github.com/AvaloniaUI/Avalonia/blob/11c542726898ae954a1ef668c65ec79ec92ab17d/src/Avalonia.Base/Collections/Pooled/PooledStack.cs#L629-L665","documentation":"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.","triggerScenarios":"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.","commonSituations":"Removing/adding items inside a foreach; reentrancy where an event handler mutates the stack during enumeration; iterating a stack that another thread mutates.","solutions":["Take a snapshot before iterating: `foreach (var x in stack.ToArray())`.","Do not mutate the stack inside the loop; collect changes and apply them after the enumeration completes.","Use a lock or copy for concurrent access."],"exampleFix":"// before\nforeach (var item in stack)\n    stack.Pop(); // mutates during enumeration\n\n// after\nforeach (var item in stack.ToArray())\n    stack.Pop();","handlingStrategy":"validation","validationCode":"foreach (var item in stack.ToArray()) // iterate a snapshot\n    Process(item); // safe to Push/Pop here","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never Push/Pop/Clear inside a foreach over the same stack.","Snapshot with ToArray() before mutating loops.","Serialize concurrent access with a lock or copy."],"tags":["csharp","pooled","stack","enumeration","invalid-operation"],"backgroundTag":null,"analyzedSha":"11c542726898ae954a1ef668c65ec79ec92ab17d","analyzedAt":"2026-08-13T11:57:40.261Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}