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
- Always gate pop() with `if (!heap.isEmpty())` or loop `while (!heap.isEmpty())`.
- If you need a safe variant, wrap pop in a helper that returns undefined on empty rather than throwing.
- 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
- Loop with `while (!heap.isEmpty())` when draining.
- Track push/pop counts in long-lived consumers to detect imbalance.
- Do not assume pop returns undefined on empty — it throws.
- Reset shared heaps between runs rather than reusing a drained instance.
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.