microsoft/FASTER · error · InvalidOperationException

The outer list is empty!

Error message

The outer list is empty!

What it means

ElasticCircularBuffer<T>.Dequeue found the head segment empty and, because head == tail, the entire outer buffer list is empty — no segment anywhere holds an item. The library throws InvalidOperationException instead of returning a default T, surfacing empty-state misuse of the elastic queue.

Solutions

  1. Check emptiness (or use TryDequeue-style logic) before Dequeue.
  2. Coordinate consumers with a condition/semaphore so they sleep while the queue is empty.
  3. Serialize consumer access so a single dequeue consumes each available item exactly once.

Example fix

// before
var item = elasticQueue.Dequeue();

// after
if (!elasticQueue.IsEmpty())
{
    var item = elasticQueue.Dequeue();
}
Defensive patterns

Strategy: validation

Validate before calling

if (elasticQueue.IsEmpty()) return default; // or block on a signal
var item = elasticQueue.Dequeue();

Try / catch

try { item = elasticQueue.Dequeue(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("outer list is empty"))
{
    item = default; // fully drained; wait for producers
}

Prevention

When it happens

Trigger: Dequeue called when all segments are drained and the outer list holds only the empty head segment equal to tail — consumers polling with no producers active.

Common situations: Consumer threads spinning on Dequeue during idle periods; multiple consumers racing to dequeue the last item; shutdown ordering where consumers outlive producers.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


AI-assisted analysis of microsoft/FASTER@321d872eab (2026-09-15). Data as JSON: /api/errors/f27632e0f7a35a21. Report an issue: GitHub.

Appendix: source

Thrown at cs/remote/src/FASTER.common/ElasticCircularBuffer.cs:154

        /// Enqueue
        /// </summary>
        /// <param name="value"></param>
        public void Enqueue(T value)
        {
            Enqueue(ref value);
        }

        /// <summary>
        /// Dequeue
        /// </summary>
        /// <returns></returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public T Dequeue()
        {
            if (head.Value.IsEmpty())
            {
                if (head == tail)
                    throw new InvalidOperationException("The outer list is empty!");

                var temp = head;
                head = head.Next;
                if (head == null) head = buffers.First;
                temp.Value.Sealed = false;
            }
            return head.Value.Dequeue();
        }

        /// <summary>
        /// Peek at head
        /// </summary>
        /// <returns></returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public T PeekFirst()
        {
            if (head.Value.head == head.Value.tail)
            {

View on GitHub (pinned to 321d872eab)