krahets/hello-algo · error · IndexError

Queue is empty

Error message

Queue is empty

What it means

ArrayQueue.peek raises IndexError('Queue is empty') when _size is zero, blocking the read of self._nums[_front]. Because pop() delegates to peek(), calling pop() on an empty queue surfaces this same exception. The guard enforces that front access is only valid when the queue holds at least one element.

Source

Thrown at en/codes/python/chapter_stack_and_queue/array_queue.py:51

        # Calculate rear pointer, points to rear index + 1
        # Use modulo operation to wrap rear around to the head after passing the tail of the array
        rear: int = (self._front + self._size) % self.capacity()
        # Add num to the rear of the queue
        self._nums[rear] = num
        self._size += 1

    def pop(self) -> int:
        """Dequeue"""
        num: int = self.peek()
        # Front pointer moves one position backward, if it passes the tail, return to the head of the array
        self._front = (self._front + 1) % self.capacity()
        self._size -= 1
        return num

    def peek(self) -> int:
        """Access front of the queue element"""
        if self.is_empty():
            raise IndexError("Queue is empty")
        return self._nums[self._front]

    def to_list(self) -> list[int]:
        """Return list for printing"""
        res = [0] * self.size()
        j: int = self._front
        for i in range(self.size()):
            res[i] = self._nums[(j % self.capacity())]
            j += 1
        return res


"""Driver Code"""
if __name__ == "__main__":
    # Initialize queue
    queue = ArrayQueue(10)

    # Elements enqueue

View on GitHub (pinned to 69932aed18)

Solutions

  1. Guard single access: `if not queue.is_empty(): head = queue.peek()`.
  2. Bound drains: `while not queue.is_empty(): x = queue.pop()`.
  3. Use queue.size() to control counted loops.
  4. Catch IndexError only when using exception-based flow control deliberately.

Example fix

// before
head = queue.peek()  # raises if empty
// after
head = queue.peek() if not queue.is_empty() else None
Defensive patterns

Strategy: validation

Validate before calling

if not queue.is_empty():
    head = queue.peek()

Type guard

def queue_nonempty(q) -> bool:
    return not q.is_empty()

Try / catch

try:
    head = queue.peek()
except IndexError:
    head = None

Prevention

When it happens

Trigger: Calling peek() or pop() on a freshly constructed queue; popping after the last element was dequeued; drain loops `while True: q.pop()` without an emptiness exit; consumer running ahead of producer.

Common situations: BFS and level-order traversals that dequeue until empty; producer/consumer pacing skew; unguarded counted dequeue loops; test code that pops more than it pushed.

Related errors


AI-assisted analysis of krahets/hello-algo@69932aed18 (2026-08-13). Data as JSON: /api/errors/baa5a00821d649e1. Report an issue: GitHub.