krahets/hello-algo · error · RangeError

Heap is empty.

Error message

Heap is empty.

What it means

Thrown by pop() on the max-heap when `isEmpty()` is true, i.e. the underlying `maxHeap` array has length 0. It is a RangeError preventing a swap/pop on an empty structure. The heap exposes no default-return path: callers must check capacity before popping.

Source

Thrown at ja/codes/typescript/chapter_heap/my_heap.ts:84

    /* ノード i から始めて、下から上へヒープ化 */
    private siftUp(i: number): void {
        while (true) {
            // ノード i の親ノードを取得
            const p = this.parent(i);
            // 「根ノードを越えた」または「ノードの修復が不要」になったらヒープ化を終了
            if (p < 0 || this.maxHeap[i] <= this.maxHeap[p]) break;
            // 2 つのノードを交換
            this.swap(i, p);
            // ループで下から上へヒープ化
            i = p;
        }
    }

    /* 要素をヒープから取り出す */
    public pop(): number {
        // 空判定の処理
        if (this.isEmpty()) throw new RangeError('Heap is empty.');
        // 根ノードと最も右の葉ノードを交換(先頭要素と末尾要素を交換)
        this.swap(0, this.size() - 1);
        // ノードを削除
        const val = this.maxHeap.pop();
        // 上から下へヒープ化
        this.siftDown(0);
        // ヒープ先頭要素を返す
        return val;
    }

    /* ノード i から始めて、上から下へヒープ化 */
    private siftDown(i: number): void {
        while (true) {
            // ノード i, l, r のうち値が最大のノードを ma とする
            const l = this.left(i),
                r = this.right(i);
            let ma = i;
            if (l < this.size() && this.maxHeap[l] > this.maxHeap[ma]) ma = l;

View on GitHub (pinned to 69932aed18)

Solutions

  1. Always gate pop() with `if (!heap.isEmpty())` or loop `while (!heap.isEmpty())`.
  2. If you need a safe variant, wrap pop in a helper that returns undefined on empty rather than throwing.
  3. Audit callers that drain the heap to ensure they stop at isEmpty.

Example fix

// before
const v = heap.pop();

// after
const v = heap.isEmpty() ? undefined : heap.pop();
Defensive patterns

Strategy: validation

Validate before calling

// Never pop an empty heap.
if (!heap.isEmpty()) {
  const v = heap.pop();
}

Type guard

function heapCanPop(heap) {
  return !heap.isEmpty();
}

Try / catch

try {
  const v = heap.pop();
} catch (e) {
  if (e instanceof RangeError && /Heap is empty/.test(e.message)) {
    // no element to pop
  } else throw e;
}

Prevention

When it happens

Trigger: Calling pop() more times than elements were pushed; calling pop() on a freshly constructed heap with no insertions; draining the heap in a loop without an isEmpty exit condition.

Common situations: Popping inside a `while (true)` loop without checking `heap.isEmpty()`; popping after an exception or early return left the heap emptier than expected; treating pop as non-failing in priority-queue consumers.

Related errors


AI-assisted analysis of krahets/hello-algo@69932aed18 (2026-08-13). Data as JSON: /api/errors/9aaf0b41ddfd9280. Report an issue: GitHub.