AvaloniaUI/Avalonia · error · InvalidOperationException
Enumeration was not started. | Enumeration has ended.
Error message
Enumeration was not started. | Enumeration has ended.
What it means
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.
Source
Thrown at src/Avalonia.Base/Collections/Pooled/PooledStack.cs:682
else
_currentElement = default;
return retval;
}
public T Current
{
get
{
if (_index < 0)
ThrowEnumerationNotStartedOrEnded();
return _currentElement!;
}
}
private void ThrowEnumerationNotStartedOrEnded()
{
Debug.Assert(_index == -1 || _index == -2);
throw new InvalidOperationException(_index == -2 ? "Enumeration was not started." : "Enumeration has ended.");
}
object? IEnumerator.Current
{
get { return Current; }
}
void IEnumerator.Reset()
{
if (_version != _stack._version)
throw new InvalidOperationException("Collection was modified during enumeration.");
_index = -2;
_currentElement = default;
}
}
}
}
View on GitHub (pinned to 11c5427268)
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.
Example fix
// before
using var e = stack.GetEnumerator();
var first = e.Current; // not started
// after
using var e = stack.GetEnumerator();
if (e.MoveNext())
var first = e.Current; Defensive patterns
Strategy: validation
Validate before calling
using var e = stack.GetEnumerator();
while (e.MoveNext())
Use(e.Current); // Current only read after MoveNext==true Prevention
- Always call MoveNext() before reading Current.
- Prefer foreach, which enforces correct ordering.
- Discard exhausted enumerators; do not read Current after MoveNext returns false.
When it happens
Trigger: Reading `enumerator.Current` before calling MoveNext, or after MoveNext has already returned false. Equivalent to the BCL enumerator rule enforced on Stack<T>.Enumerator.
Common situations: Calling Current on a freshly obtained enumerator without first calling MoveNext; reusing an exhausted enumerator; LINQ-style manual enumeration that skips the MoveNext gate.
Related errors
- Collection was modified during enumeration.
- Stack was empty.
- Collection was modified during enumeration.
- Invalid enumerator state: enumeration cannot proceed.
- Destination too short.
AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13).
Data as JSON: /api/errors/40b6a3fc9b53d62c.
Report an issue: GitHub.