{"record":{"id":"a7a3fb8a487e6e0c","repo":"krahets/hello-algo","slug":"error-a7a3fb","errorCode":null,"errorMessage":"ヒープが空です","messagePattern":"ヒープが空です","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ja/codes/javascript/chapter_heap/my_heap.js","lineNumber":85,"sourceCode":"\n    /* ノード i から始めて、下から上へヒープ化 */\n    #siftUp(i) {\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    pop() {\n        // 空判定の処理\n        if (this.isEmpty()) throw new Error('ヒープが空です');\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    #siftDown(i) {\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":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/krahets/hello-algo/blob/69932aed1891a7b7f6a0de88cd116d3fe13e7032/ja/codes/javascript/chapter_heap/my_heap.js#L67-L103","documentation":"Thrown by the max-heap's pop method when the heap is empty (isEmpty() returns true). The guard prevents swapping/reading the root of a zero-length internal array and returning an undefined value. The heap is a max-heap, so pop returns and removes the largest element.","triggerScenarios":"Calling pop() on a freshly constructed heap with no elements inserted; calling pop() more times than the number of push() calls; draining the heap in a loop without an empty check.","commonSituations":"Processing a priority queue that legitimately empties; calling pop() after clear/reset; loop conditions that assume at least one element remains.","solutions":["Check heap.isEmpty() (or heap.size() > 0) before every pop().","Use a while (!heap.isEmpty()) loop when draining the heap.","If pop is optional, skip it when empty rather than throwing.","Wrap in try/catch only when emptiness is genuinely unexpected."],"exampleFix":"// before\nconst max = heap.pop();  // throws if empty\n\n// after\nconst max = heap.isEmpty() ? null : heap.pop();","handlingStrategy":"validation","validationCode":"function safePop(heap) {\n  return heap.isEmpty() ? null : heap.pop();\n}","typeGuard":"const isNonEmpty = (heap) => typeof heap.isEmpty === 'function' && !heap.isEmpty();","tryCatchPattern":"try {\n  return heap.pop();\n} catch (e) {\n  if (e instanceof Error && e.message === 'ヒープが空です') return null;\n  throw e;\n}","preventionTips":["Always check isEmpty() before pop().","Drain with while (!heap.isEmpty()).","Return a sentinel for empty pops instead of throwing."],"tags":["heap","javascript","empty-state","priority-queue"],"backgroundTag":null,"analyzedSha":"69932aed1891a7b7f6a0de88cd116d3fe13e7032","analyzedAt":"2026-08-13T23:02:37.581Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}