dotnet/reactive · error · InvalidOperationException
Strings_Core.HEAP_EMPTY
Error message
Strings_Core.HEAP_EMPTY
What it means
Peek() on System.Reactive's internal PriorityQueue throws InvalidOperationException when the queue is empty (_size == 0). The queue requires at least one scheduled item to inspect. The library treats peeking into an empty priority queue as a programming error rather than returning a default value.
Solutions
- Check Count > 0 before calling Peek, or use TryPeek-style logic (Count check plus Peek in one thread-safe step).
- If queue may be consumed concurrently, synchronize access with a lock around Count/Peek/Dequeue calls.
- Wrap Peek in try-catch for InvalidOperationException only if racing behavior is tolerated and treated as 'queue went empty'.
Example fix
// before var next = queue.Peek(); // after if (queue.Count == 0) return; var next = queue.Peek();
Defensive patterns
Strategy: validation
Validate before calling
if (queue.Count > 0) { var next = queue.Peek(); ... } Try / catch
try { next = queue.Peek(); } catch (InvalidOperationException) { /* queue became empty */ } Prevention
- Always check Count before Peek on a PriorityQueue.
- Synchronize Count+Peek with a lock when multiple threads mutate the queue.
- Prefer TryDequeue/TryPeek-style APIs where available.
When it happens
Trigger: Calling PriorityQueue<T>.Peek() when _size == 0, i.e. before any Enqueue or after all items have been dequeued/removed. The index also surfaces via scheduled work algorithms that Peek before checking Count.
Common situations: Custom scheduler implementations or tests that call Peek on a freshly created queue; race conditions where another thread dequeued the last item between a Count check and Peek (Count/Peek not atomic).
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- AdvanceBy cannot be called when the scheduler is already…
- The scheduler operation has already been awaited.
- action
- action
- action (Parameter 'action')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/7fbbd3e9a4c7520e.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Internal/PriorityQueue.cs:90
if (first == index)
{
break;
}
// swap index and first
(_items[first], _items[index]) = (_items[index], _items[first]);
index = first;
}
}
public int Count => _size;
public T Peek()
{
if (_size == 0)
{
throw new InvalidOperationException(Strings_Core.HEAP_EMPTY);
}
return _items[0].Value;
}
private void RemoveAt(int index)
{
_items[index] = _items[--_size];
_items[_size] = default;
if (Percolate(index) == index)
{
Heapify(index);
}
if (_size < _items.Length / 4)
{
var temp = _items;View on GitHub (pinned to 94b5d5ab91)