{"record":{"id":"232db764997669d4","repo":"krahets/hello-algo","slug":"error-232db7","errorCode":null,"errorMessage":"雙向佇列為空","messagePattern":"雙向佇列為空","errorType":"exception","errorClass":"IndexError","httpStatus":null,"severity":"error","filePath":"zh-hant/codes/ruby/chapter_stack_and_queue/linkedlist_deque.rb","lineNumber":70,"sourceCode":"      node.prev = @rear\n      @rear = node # 更新尾節點\n    end\n    @size += 1 # 更新佇列長度\n  end\n\n  ### 佇列首入列 ###\n  def push_first(num)\n    push(num, true)\n  end\n\n  ### 佇列尾入列 ###\n  def push_last(num)\n    push(num, false)\n  end\n\n  ### 出列操作 ###\n  def pop(is_front)\n    raise IndexError, '雙向佇列為空' if is_empty?\n\n    # 佇列首出列操作\n    if is_front\n      val = @front.val # 暫存頭節點值\n      # 刪除頭節點\n      fnext = @front.next\n      unless fnext.nil?\n        fnext.prev = nil\n        @front.next = nil\n      end\n      @front = fnext # 更新頭節點\n    # 佇列尾出列操作\n    else\n      val = @rear.val # 暫存尾節點值\n      # 刪除尾節點\n      rprev = @rear.prev\n      unless rprev.nil?\n        rprev.next = nil","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/krahets/hello-algo/blob/69932aed1891a7b7f6a0de88cd116d3fe13e7032/zh-hant/codes/ruby/chapter_stack_and_queue/linkedlist_deque.rb#L52-L88","documentation":"Raised by the private pop(is_front) method of the LinkedListDeque teaching class (a doubly-linked-list double-ended queue) when is_empty? is true. Both pop_first and pop_last delegate to this method, so attempting to dequeue from either end of an empty deque triggers it. The guard fires before any node pointer manipulation.","triggerScenarios":"Calling deque.pop_first or deque.pop_last on a new deque (size 0), calling them after all elements have been removed, or draining past empty in a loop.","commonSituations":"Unbalanced push/pop calls; assuming the deque has elements after construction; draining with a fixed count instead of an emptiness check.","solutions":["Check deque.is_empty? before calling pop_first or pop_last.","Use while !deque.is_empty? to drain both ends safely.","Return nil when empty: deque.is_empty? ? nil : deque.pop_first.","Wrap in begin/rescue IndexError for defensive dequeue."],"exampleFix":"# before\n5.times { deque.pop_first }  # raises if fewer than 5 elements\n\n# after\nuntil deque.is_empty?\n  deque.pop_first\nend","handlingStrategy":"validation","validationCode":"return nil if deque.is_empty?\ndeque.pop_first  # or pop_last","typeGuard":"# Ruby: safe pop from either end\ndef safe_pop_first(deque)\n  deque.is_empty? ? nil : deque.pop_first\nend","tryCatchPattern":"begin\n  val = deque.pop_first\nrescue IndexError\n  val = nil\nend","preventionTips":["Check is_empty? before pop_first or pop_last (both delegate to pop).","Use 'until deque.is_empty?' for draining.","Track push/pop counts for both ends."],"tags":["ruby","index-error","data-structures","deque","empty-state","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"}