deepset-ai/haystack · error · IndexError
pop from empty queue
Error message
pop from empty queue
What it means
FifoPriorityQueue.pop raises IndexError('pop from empty queue') when called on an empty queue (utils.py:124). Unlike heapq.heappop's bare IndexError, this gives an explicit message. It is an internal scheduling queue used by the pipeline runner's helpers, so hitting it usually means calling pop without checking emptiness.
Source
Thrown at haystack/core/pipeline/utils.py:124
Priority level for the item. Lower numbers indicate higher priority.
"""
next_count = next(self._counter)
entry = (priority, next_count, item)
heapq.heappush(self._queue, entry)
def pop(self) -> tuple[int, Any]:
"""
Remove and return the highest priority item from the queue.
For items with equal priority, returns the one that was inserted first.
:returns:
A tuple containing (priority, item) with the lowest priority number.
:raises IndexError:
If the queue is empty.
"""
if not self._queue:
raise IndexError("pop from empty queue")
priority, _, item = heapq.heappop(self._queue)
return priority, item
def peek(self) -> tuple[int, Any]:
"""
Return but don't remove the highest priority item from the queue.
For items with equal priority, returns the one that was inserted first.
:returns:
A tuple containing (priority, item) with the lowest priority number.
:raises IndexError:
If the queue is empty.
"""
if not self._queue:
raise IndexError("peek at empty queue")
priority, _, item = self._queue[0]
return priority, itemView on GitHub (pinned to e318778c9b)
Solutions
- Use get(), which returns None on an empty queue, instead of pop().
- Guard with if not queue.is_empty(): queue.pop() or wrap in try/except IndexError.
- Check loop conditions: use the queue's emptiness API rather than exception-driven termination.
Example fix
// before
while True:
priority, task = queue.pop()
// after
while not queue.is_empty():
item = queue.get()
if item is None:
break
Defensive patterns
Strategy: try-catch
Validate before calling
if queue.is_empty():
return None Try / catch
try:
priority, item = queue.pop()
except IndexError:
priority, item = None, None Prevention
- Prefer the non-raising get() API when draining a queue.
- Check is_empty() before destructive operations.
- Avoid exception-driven loop termination in scheduler code.
When it happens
Trigger: Calling queue.pop() when is_empty(); race between a size/is_empty check and pop in concurrent code; iterating until peek raises instead of using get().
Common situations: Custom runner code or tests consuming pipeline queue helpers; off-by-one loops around task scheduling; draining a queue with pop instead of the non-raising get().
Related errors
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/2fe8ec371f6604ae.
Report an issue: GitHub.