{"record":{"id":"9aaf0b41ddfd9280","repo":"krahets/hello-algo","slug":"heap-is-empty-9aaf0b","errorCode":null,"errorMessage":"Heap is empty.","messagePattern":"Heap is empty\\.","errorType":"exception","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"ja/codes/typescript/chapter_heap/my_heap.ts","lineNumber":84,"sourceCode":"\n    /* ノード i から始めて、下から上へヒープ化 */\n    private siftUp(i: number): void {\n        while (true) {\n            // ノード i の親ノードを取得\n            const p = this.parent(i);\n            // 「根ノードを越えた」または「ノードの修復が不要」になったらヒープ化を終了\n            if (p < 0 || this.maxHeap[i] <= this.maxHeap[p]) break;\n            // 2 つのノードを交換\n            this.swap(i, p);\n            // ループで下から上へヒープ化\n            i = p;\n        }\n    }\n\n    /* 要素をヒープから取り出す */\n    public pop(): number {\n        // 空判定の処理\n        if (this.isEmpty()) throw new RangeError('Heap is empty.');\n        // 根ノードと最も右の葉ノードを交換（先頭要素と末尾要素を交換）\n        this.swap(0, this.size() - 1);\n        // ノードを削除\n        const val = this.maxHeap.pop();\n        // 上から下へヒープ化\n        this.siftDown(0);\n        // ヒープ先頭要素を返す\n        return val;\n    }\n\n    /* ノード i から始めて、上から下へヒープ化 */\n    private siftDown(i: number): void {\n        while (true) {\n            // ノード i, l, r のうち値が最大のノードを ma とする\n            const l = this.left(i),\n                r = this.right(i);\n            let ma = i;\n            if (l < this.size() && this.maxHeap[l] > this.maxHeap[ma]) ma = l;","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/krahets/hello-algo/blob/69932aed1891a7b7f6a0de88cd116d3fe13e7032/ja/codes/typescript/chapter_heap/my_heap.ts#L66-L102","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst v = heap.pop();\n\n// after\nconst v = heap.isEmpty() ? undefined : heap.pop();","handlingStrategy":"validation","validationCode":"// Never pop an empty heap.\nif (!heap.isEmpty()) {\n  const v = heap.pop();\n}","typeGuard":"function heapCanPop(heap) {\n  return !heap.isEmpty();\n}","tryCatchPattern":"try {\n  const v = heap.pop();\n} catch (e) {\n  if (e instanceof RangeError && /Heap is empty/.test(e.message)) {\n    // no element to pop\n  } else throw e;\n}","preventionTips":["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."],"tags":["heap","empty-state","range-error","typescript"],"backgroundTag":null,"analyzedSha":"69932aed1891a7b7f6a0de88cd116d3fe13e7032","analyzedAt":"2026-08-13T23:02:37.581Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}