{"record":{"id":"adba726e164c1f6d","repo":"krahets/hello-algo","slug":"deque-is-empty-adba72","errorCode":null,"errorMessage":"Deque is empty","messagePattern":"Deque is empty","errorType":"exception","errorClass":"IndexError","httpStatus":null,"severity":"error","filePath":"en/codes/ruby/chapter_stack_and_queue/linkedlist_deque.rb","lineNumber":70,"sourceCode":"      node.prev = @rear\n      @rear = node # Update tail node\n    end\n    @size += 1 # Update queue length\n  end\n\n  ### Enqueue at front ###\n  def push_first(num)\n    push(num, true)\n  end\n\n  ### Enqueue at rear ###\n  def push_last(num)\n    push(num, false)\n  end\n\n  ### Dequeue operation ###\n  def pop(is_front)\n    raise IndexError, 'Deque is empty' if is_empty?\n\n    # Temporarily store head node value\n    if is_front\n      val = @front.val # Delete head node\n      # Delete head node\n      fnext = @front.next\n      unless fnext.nil?\n        fnext.prev = nil\n        @front.next = nil\n      end\n      @front = fnext # Update head node\n    # Temporarily store tail node value\n    else\n      val = @rear.val # Delete tail node\n      # Update tail node\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/en/codes/ruby/chapter_stack_and_queue/linkedlist_deque.rb#L52-L88","documentation":"Raised by LinkedListDeque#pop (en/codes/ruby/chapter_stack_and_queue/linkedlist_deque.rb:70) when the deque is empty. pop(is_front) unlinks either @front or @rear; the guard rejects the operation because there is no node to unlink when size == 0. The public pop_first/pop_last delegate here, so both surface the same message.","triggerScenarios":"Calling deque.pop_first or deque.pop_last when deque.size == 0. Occurs after removing every node, or immediately after LinkedListDeque.new with no push_first/push_last calls.","commonSituations":"A sliding-window or palindrome/buffer routine that pops both ends and overshoots; a deque used as a work-list where every task is consumed; test code that pops in pairs without checking size.","solutions":["Check deque.is_empty? before pop_first/pop_last.","Verify deque.size >= 1 (or >= 2 for paired pops) before removing.","Rescue IndexError around the pop and treat empty as the loop's exit condition."],"exampleFix":"# before\nwhile true\n  deque.pop_last # raises once drained\nend\n\n# after\nuntil deque.is_empty?\n  deque.pop_last\nend","handlingStrategy":"validation","validationCode":"deque.pop_first unless deque.is_empty?","typeGuard":"def deque_nonempty?(d); d.respond_to?(:is_empty?) && !d.is_empty?; end","tryCatchPattern":"begin\n  deque.pop_last\nrescue IndexError\n  nil\nend","preventionTips":["Check is_empty? before pop_first/pop_last.","For paired front+rear pops, require size >= 2 first.","Make size == 0 the termination condition of drain loops."],"tags":["ruby","deque","linked-list","precondition","indexerror"],"backgroundTag":null,"analyzedSha":"69932aed1891a7b7f6a0de88cd116d3fe13e7032","analyzedAt":"2026-08-13T23:02:37.581Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}