{"record":{"id":"40b6a3fc9b53d62c","repo":"AvaloniaUI/Avalonia","slug":"enumeration-was-not-started-enumeration-has-end","errorCode":null,"errorMessage":"Enumeration was not started. | Enumeration has ended.","messagePattern":"Enumeration was not started\\. \\| Enumeration has ended\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Avalonia.Base/Collections/Pooled/PooledStack.cs","lineNumber":682,"sourceCode":"                else\n                    _currentElement = default;\n                return retval;\n            }\n\n            public T Current\n            {\n                get\n                {\n                    if (_index < 0)\n                        ThrowEnumerationNotStartedOrEnded();\n                    return _currentElement!;\n                }\n            }\n\n            private void ThrowEnumerationNotStartedOrEnded()\n            {\n                Debug.Assert(_index == -1 || _index == -2);\n                throw new InvalidOperationException(_index == -2 ? \"Enumeration was not started.\" : \"Enumeration has ended.\");\n            }\n\n            object? IEnumerator.Current\n            {\n                get { return Current; }\n            }\n\n            void IEnumerator.Reset()\n            {\n                if (_version != _stack._version)\n                    throw new InvalidOperationException(\"Collection was modified during enumeration.\");\n                _index = -2;\n                _currentElement = default;\n            }\n        }\n    }\n}\n","sourceCodeStart":664,"sourceCodeEnd":700,"githubUrl":"https://github.com/AvaloniaUI/Avalonia/blob/11c542726898ae954a1ef668c65ec79ec92ab17d/src/Avalonia.Base/Collections/Pooled/PooledStack.cs#L664-L700","documentation":"InvalidOperationException from the PooledStack enumerator's Current getter via ThrowEnumerationNotStartedOrEnded, which selects the message by index: `-2` (before first MoveNext) yields \"Enumeration was not started.\", `-1` (after MoveNext returned false) yields \"Enumeration has ended.\". It prevents reading Current outside a valid enumeration position.","triggerScenarios":"Reading `enumerator.Current` before calling MoveNext, or after MoveNext has already returned false. Equivalent to the BCL enumerator rule enforced on Stack<T>.Enumerator.","commonSituations":"Calling Current on a freshly obtained enumerator without first calling MoveNext; reusing an exhausted enumerator; LINQ-style manual enumeration that skips the MoveNext gate.","solutions":["Always call MoveNext() and check its return before reading Current.","Prefer `foreach` which guarantees correct MoveNext/Current ordering.","Discard an exhausted enumerator and obtain a fresh one rather than reading Current again."],"exampleFix":"// before\nusing var e = stack.GetEnumerator();\nvar first = e.Current; // not started\n\n// after\nusing var e = stack.GetEnumerator();\nif (e.MoveNext())\n    var first = e.Current;","handlingStrategy":"validation","validationCode":"using var e = stack.GetEnumerator();\nwhile (e.MoveNext())\n    Use(e.Current); // Current only read after MoveNext==true","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always call MoveNext() before reading Current.","Prefer foreach, which enforces correct ordering.","Discard exhausted enumerators; do not read Current after MoveNext returns false."],"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"}