{"record":{"id":"1f7b79a9bdba78ca","repo":"krahets/hello-algo","slug":"error-1f7b79","errorCode":null,"errorMessage":"双向队列为空","messagePattern":"双向队列为空","errorType":"exception","errorClass":"IndexError","httpStatus":null,"severity":"error","filePath":"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/codes/ruby/chapter_stack_and_queue/linkedlist_deque.rb#L52-L88","documentation":"Raised by `LinkedListDeque#pop` (linkedlist_deque.rb:70) when `is_empty?` is true. This is the internal pop shared by `pop_first` and `pop_last`; on an empty deque there is no node to detach, and dereferencing `@front.val` or `@rear.val` would fail. The guard prevents nil-dereference on the linked-list head/tail pointers.","triggerScenarios":"Calling `deque.pop_first` or `deque.pop_last` (both delegate to `pop`) on a deque with zero nodes. Occurs after removing all elements from both ends.","commonSituations":"Deque-based undo/redo fully consumed; deque used as a work-queue drained to empty; test calling pop on a new deque.","solutions":["Check `deque.is_empty?` before `pop_first` or `pop_last`.","Loop with `until deque.is_empty?` when draining.","Rescue IndexError if popping past empty is recoverable."],"exampleFix":"# before\nval = deque.pop_first\n\n# after\nval = deque.is_empty? ? nil : deque.pop_first","handlingStrategy":"validation","validationCode":"return nil if deque.is_empty?\ndeque.pop_first","typeGuard":"def ll_deque_popable?(deque)\n  deque.respond_to?(:is_empty?) && deque.respond_to?(:pop) && !deque.is_empty?\nend","tryCatchPattern":"begin\n  deque.pop_first\nrescue IndexError\n  nil\nend","preventionTips":["Check is_empty? before pop_first or pop_last.","Drain with until deque.is_empty? instead of a fixed count.","Validate size before each two-ended consume step."],"tags":["ruby","deque","linked-list","precondition","empty-state"],"backgroundTag":null,"analyzedSha":"69932aed1891a7b7f6a0de88cd116d3fe13e7032","analyzedAt":"2026-08-13T23:02:37.581Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}