{"record":{"id":"27b9cfff600a4e5f","repo":"krahets/hello-algo","slug":"error-27b9cf","errorCode":null,"errorMessage":"двусторонняя очередь пуста","messagePattern":"двусторонняя очередь пуста","errorType":"exception","errorClass":"IndexError","httpStatus":null,"severity":"error","filePath":"ru/codes/python/chapter_stack_and_queue/linkedlist_deque.py","lineNumber":66,"sourceCode":"        else:\n            # Добавить node в хвост списка\n            self._rear.next = node\n            node.prev = self._rear\n            self._rear = node  # Обновить хвостовой узел\n        self._size += 1  # Обновить длину очереди\n\n    def push_first(self, num: int):\n        \"\"\"Добавление в голову очереди\"\"\"\n        self.push(num, True)\n\n    def push_last(self, num: int):\n        \"\"\"Добавление в хвост очереди\"\"\"\n        self.push(num, False)\n\n    def pop(self, is_front: bool) -> int:\n        \"\"\"Операция извлечения из очереди\"\"\"\n        if self.is_empty():\n            raise IndexError(\"двусторонняя очередь пуста\")\n        # Операция извлечения из головы очереди\n        if is_front:\n            val: int = self._front.val  # Временно сохранить значение головного узла\n            # Удалить головной узел\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  # Обновить головной узел\n        # Операция извлечения из хвоста очереди\n        else:\n            val: int = self._rear.val  # Временно сохранить значение хвостового узла\n            # Удалить хвостовой узел\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  # Обновить хвостовой узел","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/krahets/hello-algo/blob/69932aed1891a7b7f6a0de88cd116d3fe13e7032/ru/codes/python/chapter_stack_and_queue/linkedlist_deque.py#L48-L84","documentation":"Raised by LinkedListDeque.pop(is_front) in chapter_stack_and_queue/linkedlist_deque.py:66 — IndexError(\"двусторонняя очередь пуста\"). This is the internal removal routine called by pop_first()/pop_last(); it refuses to unlink from an empty deque because self._front/self._rear would be None. Note the public API is pop_first()/pop_last(); pop(is_front) is the shared private helper.","triggerScenarios":"Calling pop_first() or pop_last() on an empty deque (both delegate here). More pops than pushes from either end. Asymmetric use (push only on one end, pop on the other) until drained.","commonSituations":"Palindrome/two-pointer deque algorithms that overshoot the middle. Consumer outrunning producer on a shared deque. Cleanup that pops remaining elements twice.","solutions":["Guard the public call: if not dq.is_empty(): dq.pop_first().","Use is_empty() as the termination condition for two-ended draining.","Wrap pop_first/pop_last in try/except IndexError for best-effort removal.","Track logical element count so pops never exceed pushes."],"exampleFix":"// before\nx = dq.pop_first()\n// after\nx = dq.pop_first() if not dq.is_empty() else None","handlingStrategy":"validation","validationCode":"def safe_pop_first(dq):\n    return dq.pop_first() if not dq.is_empty() else None","typeGuard":"def deque_non_empty(dq) -> bool:\n    return not dq.is_empty()","tryCatchPattern":"try:\n    x = dq.pop_first()  # delegates to private pop(is_front=True)\nexcept IndexError:\n    x = None","preventionTips":["Call the public pop_first/pop_last, not the private pop(is_front)","Use is_empty() as the two-ended drain condition","Track logical count so pops never exceed pushes"],"tags":["indexerror","deque","linked-list","precondition","empty-state","python"],"backgroundTag":null,"analyzedSha":"69932aed1891a7b7f6a0de88cd116d3fe13e7032","analyzedAt":"2026-08-13T23:02:37.581Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}