{"record":{"id":"58cc01ee60cb094c","repo":"krahets/hello-algo","slug":"heap-is-empty-58cc01","errorCode":null,"errorMessage":"Heap is empty.","messagePattern":"Heap is empty\\.","errorType":"exception","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"en/codes/typescript/chapter_heap/my_heap.ts","lineNumber":84,"sourceCode":"\n    /* Starting from node i, heapify from bottom to top */\n    private siftUp(i: number): void {\n        while (true) {\n            // Get parent node of node i\n            const p = this.parent(i);\n            // When \"crossing root node\" or \"node needs no repair\", end heapify\n            if (p < 0 || this.maxHeap[i] <= this.maxHeap[p]) break;\n            // Swap two nodes\n            this.swap(i, p);\n            // Loop upward heapify\n            i = p;\n        }\n    }\n\n    /* Element exits heap */\n    public pop(): number {\n        // Handle empty case\n        if (this.isEmpty()) throw new RangeError('Heap is empty.');\n        // Delete node\n        this.swap(0, this.size() - 1);\n        // Remove node\n        const val = this.maxHeap.pop();\n        // Return top element\n        this.siftDown(0);\n        // Return heap top element\n        return val;\n    }\n\n    /* Starting from node i, heapify from top to bottom */\n    private siftDown(i: number): void {\n        while (true) {\n            // If node i is largest or indices l, r are out of bounds, no need to continue heapify, break\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/en/codes/typescript/chapter_heap/my_heap.ts#L66-L102","documentation":"Thrown by MaxHeap.pop when the heap is empty. pop swaps the root with the last element, removes it, and re-heapifies; with zero elements those steps are meaningless and would return undefined, so the method throws a RangeError to signal the precondition violation.","triggerScenarios":"Calling pop on a freshly constructed heap with no inserts; calling pop more times than elements were pushed; interleaving pop with failed pushes so the count is lower than expected.","commonSituations":"Drain loops that do not check isEmpty; priority-queue consumers that pop on every tick regardless of fill level; off-by-one in loop counters.","solutions":["Guard every pop with isEmpty() (or size() > 0) first.","Use a while (!heap.isEmpty()) loop for draining.","Return an Option/sentinel from a wrapper instead of letting pop throw."],"exampleFix":"// before\nconst top = heap.pop(); // throws if empty\n\n// after\nconst top = heap.isEmpty() ? undefined : heap.pop();","handlingStrategy":"validation","validationCode":"const top = heap.isEmpty() ? undefined : heap.pop();","typeGuard":"function hasElements(h) { return typeof h.isEmpty === 'function' && !h.isEmpty(); }","tryCatchPattern":"try { return heap.pop(); }\ncatch (e) { if (!(e instanceof RangeError)) throw e; return undefined; }","preventionTips":["Always pair pop with an isEmpty() check.","Drain with while (!heap.isEmpty()).","Wrap pop in a helper that returns an Option for pipeline safety."],"tags":["heap","typescript","validation","guard-clause","empty-state"],"backgroundTag":null,"analyzedSha":"69932aed1891a7b7f6a0de88cd116d3fe13e7032","analyzedAt":"2026-08-13T23:02:37.581Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}