{"record":{"id":"7938671e988f4058","repo":"krahets/hello-algo","slug":"error-793867","errorCode":null,"errorMessage":"両端キューが空です","messagePattern":"両端キューが空です","errorType":"exception","errorClass":"IndexError","httpStatus":null,"severity":"error","filePath":"ja/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/ja/codes/python/chapter_stack_and_queue/linkedlist_deque.py#L48-L84","documentation":"This IndexError (Japanese: '両端キューが空です' = 'deque is empty') is raised by LinkedListDeque.pop(is_front) (linkedlist_deque.py:66) when _size == 0. pop() reads _front.val or _rear.val; on an empty deque both pointers are None, so accessing .val would raise AttributeError — the guard prevents that. pop_first()/pop_last() delegate here, so the exception surfaces through both.","triggerScenarios":"Calling pop_first() or pop_last() on a freshly constructed LinkedListDeque (size 0). Calling pop more times than push. The linked-list deque is unbounded (no capacity limit), so 'empty' is the only failure mode from pop.","commonSituations":"Draining both ends in a sliding-window or palindrome-style algorithm and over-popping. Treating None pointers as safe-to-deref. Holding references after the deque was emptied elsewhere.","solutions":["Guard with `if not dq.is_empty(): dq.pop_first()` (or pop_last).","Drain via `while not dq.is_empty():`.","Track the number of outstanding elements externally and never pop beyond it.","Wrap pop_first/pop_last in try/except IndexError for tolerant consumers."],"exampleFix":"// before\nval = dq.pop_first()  # IndexError when empty\n\n// after\nval = dq.pop_first() if not dq.is_empty() else None","handlingStrategy":"validation","validationCode":"if not dq.is_empty():\n    val = dq.pop_first()\n# pop_last() delegates to the same pop() — guard identically","typeGuard":"def deque_has_element(dq: LinkedListDeque) -> bool:\n    return not dq.is_empty()","tryCatchPattern":"try:\n    val = dq.pop_first()\nexcept IndexError:\n    val = None","preventionTips":["Guard pop_first()/pop_last() with is_empty() — both share pop().","The linked-list deque is unbounded, so only underflow is possible.","Drain with `while not dq.is_empty():`.","Track outstanding elements in two-ended algorithms to avoid over-popping."],"tags":["deque","python","index-error","empty","linked-list","doubly-linked-list"],"backgroundTag":null,"analyzedSha":"69932aed1891a7b7f6a0de88cd116d3fe13e7032","analyzedAt":"2026-08-13T23:02:37.581Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}