deepset-ai/haystack · error · IndexError
peek at empty queue
Error message
peek at empty queue
What it means
FifoPriorityQueue.peek raises IndexError('peek at empty queue') when inspecting the front of an empty queue (utils.py:140). peek is non-destructive but still requires at least one item. Used by pipeline validation and scheduling helpers.
Source
Thrown at haystack/core/pipeline/utils.py:140
"""
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, item
def get(self) -> tuple[int, Any] | None:
"""
Remove and return the highest priority item from the queue.
For items with equal priority, returns the one that was inserted first.
Unlike pop(), returns None if the queue is empty instead of raising an exception.
:returns:
A tuple containing (priority, item), or None if the queue is empty.
"""
if not self._queue:
return None
priority, _, item = heapq.heappop(self._queue)
return priority, item
View on GitHub (pinned to e318778c9b)
Solutions
- Check is_empty() before peeking.
- Wrap in try/except IndexError, or use get() which returns None when empty.
- Restructure logic to push a sentinel/terminator item instead of peeking on a possibly empty queue.
Example fix
// before
priority, task = queue.peek()
// after
if not queue.is_empty():
priority, task = queue.peek()
Defensive patterns
Strategy: try-catch
Validate before calling
if queue.is_empty():
return None Try / catch
try:
priority, item = queue.peek()
except IndexError:
priority, item = None, None Prevention
- Guard peek with is_empty() in scheduling/validation loops.
- Use get() (returns None when empty) where a non-raising read suffices.
- Re-check emptiness after any await in concurrent code.
When it happens
Trigger: Calling peek() before any push(); peeking after the queue was drained; validation paths in validate_pipeline touching an empty queue.
Common situations: Pre-run inspection code in tests; scheduling loops that peek to decide next steps when no tasks remain; stale assumptions that the queue is non-empty after awaits.
Related errors
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/95d00002f7edb2fe.
Report an issue: GitHub.