{"record":{"id":"8df851c3fb87e2f6","repo":"krahets/hello-algo","slug":"the-deque-is-empty","errorCode":null,"errorMessage":"The Deque Is Empty.","messagePattern":"The Deque Is Empty\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"codes/javascript/chapter_stack_and_queue/array_deque.js","lineNumber":88,"sourceCode":"    /* 队首出队 */\n    popFirst() {\n        const num = this.peekFirst();\n        // 队首指针向后移动一位\n        this.#front = this.index(this.#front + 1);\n        this.#queSize--;\n        return num;\n    }\n\n    /* 队尾出队 */\n    popLast() {\n        const num = this.peekLast();\n        this.#queSize--;\n        return num;\n    }\n\n    /* 访问队首元素 */\n    peekFirst() {\n        if (this.isEmpty()) throw new Error('The Deque Is Empty.');\n        return this.#nums[this.#front];\n    }\n\n    /* 访问队尾元素 */\n    peekLast() {\n        if (this.isEmpty()) throw new Error('The Deque Is Empty.');\n        // 计算尾元素索引\n        const last = this.index(this.#front + this.#queSize - 1);\n        return this.#nums[last];\n    }\n\n    /* 返回数组用于打印 */\n    toArray() {\n        // 仅转换有效长度范围内的列表元素\n        const res = [];\n        for (let i = 0, j = this.#front; i < this.#queSize; i++, j++) {\n            res[i] = this.#nums[this.index(j)];\n        }","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/krahets/hello-algo/blob/69932aed1891a7b7f6a0de88cd116d3fe13e7032/codes/javascript/chapter_stack_and_queue/array_deque.js#L70-L106","documentation":"Thrown by peekFirst() on a circular-array deque when the deque is empty. peekFirst reads #nums[this.#front]; with queSize 0 the front slot holds stale data, so the guard prevents returning a garbage value. popFirst() calls peekFirst() internally, so the same throw surfaces from both.","triggerScenarios":"Calling peekFirst()/popFirst() on a freshly constructed deque; calling after all elements were popped; off-by-one in a drain loop; reading the front of a deque that was never pushed to.","commonSituations":"Mismatched push/pop counts; BFS/DFS frontier draining; producer-consumer where the consumer races ahead.","solutions":["Check deque.isEmpty() (or size() === 0) before peekFirst/popFirst.","Drain with while (!dq.isEmpty()) rather than a counted loop.","Maintain a parallel counter or use a sentinel for empty-state signaling.","Validate input batch sizes before processing."],"exampleFix":"// before\nconst head = dq.peekFirst(); // throws if empty\n// after\nconst head = dq.isEmpty() ? null : dq.peekFirst();","handlingStrategy":"validation","validationCode":"function safePeekFirst(dq) {\n  return dq.isEmpty() ? null : dq.peekFirst();\n}","typeGuard":"function dequeNotEmpty(dq) {\n  return dq.size() > 0;\n}","tryCatchPattern":"try {\n  const head = dq.peekFirst();\n} catch (e) {\n  if (e instanceof Error && e.message === 'The Deque Is Empty.') { /* handle empty */ } else throw e;\n}","preventionTips":["Check dq.isEmpty() before peekFirst/popFirst.","Drain with while (!dq.isEmpty()) rather than counted loops.","Keep push/pop counts balanced.","Use a sentinel return (null) wrapper in library code."],"tags":["deque","empty-state","javascript","circular-array"],"backgroundTag":null,"analyzedSha":"69932aed1891a7b7f6a0de88cd116d3fe13e7032","analyzedAt":"2026-08-13T23:02:37.581Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}