krahets/hello-algo · error · IndexError
両端キューが空です
Error message
両端キューが空です
What it means
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.
Source
Thrown at ja/codes/python/chapter_stack_and_queue/linkedlist_deque.py:66
else:
# node を連結リストの末尾に追加
self._rear.next = node
node.prev = self._rear
self._rear = node # 末尾ノードを更新する
self._size += 1 # キューの長さを更新
def push_first(self, num: int):
"""キュー先頭にエンキュー"""
self.push(num, True)
def push_last(self, num: int):
"""キュー末尾にエンキュー"""
self.push(num, False)
def pop(self, is_front: bool) -> int:
"""デキュー操作"""
if self.is_empty():
raise IndexError("両端キューが空です")
# キュー先頭からの取り出し
if is_front:
val: int = self._front.val # 先頭ノードの値を一時保存
# 先頭ノードを削除
fnext: ListNode | None = self._front.next
if fnext is not None:
fnext.prev = None
self._front.next = None
self._front = fnext # 先頭ノードを更新する
# キュー末尾からの取り出し
else:
val: int = self._rear.val # 末尾ノードの値を一時保存
# 末尾ノードを削除
rprev: ListNode | None = self._rear.prev
if rprev is not None:
rprev.next = None
self._rear.prev = None
self._rear = rprev # 末尾ノードを更新するView on GitHub (pinned to 69932aed18)
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.
Example fix
// before val = dq.pop_first() # IndexError when empty // after val = dq.pop_first() if not dq.is_empty() else None
Defensive patterns
Strategy: validation
Validate before calling
if not dq.is_empty():
val = dq.pop_first()
# pop_last() delegates to the same pop() — guard identically Type guard
def deque_has_element(dq: LinkedListDeque) -> bool:
return not dq.is_empty() Try / catch
try:
val = dq.pop_first()
except IndexError:
val = None Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
AI-assisted analysis of krahets/hello-algo@69932aed18 (2026-08-13).
Data as JSON: /api/errors/7938671e988f4058.
Report an issue: GitHub.