{"record":{"id":"601eb07b74ab085b","repo":"krahets/hello-algo","slug":"double-ended-queue-is-empty-601eb0","errorCode":null,"errorMessage":"Double-ended queue is empty","messagePattern":"Double-ended queue is empty","errorType":"exception","errorClass":"IndexError","httpStatus":null,"severity":"error","filePath":"en/codes/python/chapter_stack_and_queue/linkedlist_deque.py","lineNumber":66,"sourceCode":"        else:\n            # Add node to the tail of the linked list\n            self._rear.next = node\n            node.prev = self._rear\n            self._rear = node  # Update tail node\n        self._size += 1  # Update queue length\n\n    def push_first(self, num: int):\n        \"\"\"Front of the queue enqueue\"\"\"\n        self.push(num, True)\n\n    def push_last(self, num: int):\n        \"\"\"Rear of the queue enqueue\"\"\"\n        self.push(num, False)\n\n    def pop(self, is_front: bool) -> int:\n        \"\"\"Dequeue operation\"\"\"\n        if self.is_empty():\n            raise IndexError(\"Double-ended queue is empty\")\n        # Front of the queue dequeue operation\n        if is_front:\n            val: int = self._front.val  # Temporarily store head node value\n            # Delete head node\n            fnext: ListNode | None = self._front.next\n            if fnext is not None:\n                fnext.prev = None\n                self._front.next = None\n            self._front = fnext  # Update head node\n        # Rear of the queue dequeue operation\n        else:\n            val: int = self._rear.val  # Temporarily store tail node value\n            # Delete tail node\n            rprev: ListNode | None = self._rear.prev\n            if rprev is not None:\n                rprev.next = None\n                self._rear.prev = None\n            self._rear = rprev  # Update tail node","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/krahets/hello-algo/blob/69932aed1891a7b7f6a0de88cd116d3fe13e7032/en/codes/python/chapter_stack_and_queue/linkedlist_deque.py#L48-L84","documentation":"LinkedListDeque.pop (the internal dequeue used by pop_first/pop_last) raises IndexError('Double-ended queue is empty') when is_empty() is true, before attempting to dereference self._front.val / self._rear.val. Because the linked-list head/tail pointers are None when empty, the guard prevents an AttributeError on .val and gives a clear message. Both pop_first and pop_last route through this method.","triggerScenarios":"Calling pop_first()/pop_last() on an empty deque; calling pop after the last node was detached; unguarded drain loops alternating front/rear pops; deque used as a stack/queue drained past empty.","commonSituations":"BFS/DFS with a linked deque; sliding-window deque emptied by pops; undo/redo on a linked structure; algorithms that pop from whichever end is cheaper without checking size.","solutions":["Guard with the predicate: `if not deque.is_empty(): deque.pop_first()`.","Bound drains: `while not deque.is_empty(): ...`.","Use deque.size() to drive counted loops.","Wrap pop in a helper returning Optional when empty states are expected."],"exampleFix":"// before\nval = deque.pop_first()  # raises if empty\n// after\nval = deque.pop_first() if not deque.is_empty() else None","handlingStrategy":"validation","validationCode":"if not deque.is_empty():\n    val = deque.pop_first()","typeGuard":"def deque_nonempty(d) -> bool:\n    return not d.is_empty()","tryCatchPattern":"try:\n    val = deque.pop_first()\nexcept IndexError:\n    val = None","preventionTips":["Drive linked-deque drains with `while not deque.is_empty()`.","Bound counted loops with size().","Wrap pop_first/pop_last in helpers returning Optional."],"tags":["deque","linkedlist","indexerror","empty-state","python","data-structures"],"backgroundTag":null,"analyzedSha":"69932aed1891a7b7f6a0de88cd116d3fe13e7032","analyzedAt":"2026-08-13T23:02:37.581Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}