krahets/hello-algo · error · Error
The Deque Is Empty.
Error message
The Deque Is Empty.
What it means
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.
Source
Thrown at codes/javascript/chapter_stack_and_queue/array_deque.js:88
/* 队首出队 */
popFirst() {
const num = this.peekFirst();
// 队首指针向后移动一位
this.#front = this.index(this.#front + 1);
this.#queSize--;
return num;
}
/* 队尾出队 */
popLast() {
const num = this.peekLast();
this.#queSize--;
return num;
}
/* 访问队首元素 */
peekFirst() {
if (this.isEmpty()) throw new Error('The Deque Is Empty.');
return this.#nums[this.#front];
}
/* 访问队尾元素 */
peekLast() {
if (this.isEmpty()) throw new Error('The Deque Is Empty.');
// 计算尾元素索引
const last = this.index(this.#front + this.#queSize - 1);
return this.#nums[last];
}
/* 返回数组用于打印 */
toArray() {
// 仅转换有效长度范围内的列表元素
const res = [];
for (let i = 0, j = this.#front; i < this.#queSize; i++, j++) {
res[i] = this.#nums[this.index(j)];
}View on GitHub (pinned to 69932aed18)
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.
Example fix
// before const head = dq.peekFirst(); // throws if empty // after const head = dq.isEmpty() ? null : dq.peekFirst();
Defensive patterns
Strategy: validation
Validate before calling
function safePeekFirst(dq) {
return dq.isEmpty() ? null : dq.peekFirst();
} Type guard
function dequeNotEmpty(dq) {
return dq.size() > 0;
} Try / catch
try {
const head = dq.peekFirst();
} catch (e) {
if (e instanceof Error && e.message === 'The Deque Is Empty.') { /* handle empty */ } else throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Mismatched push/pop counts; BFS/DFS frontier draining; producer-consumer where the consumer races ahead.
Related errors
AI-assisted analysis of krahets/hello-algo@69932aed18 (2026-08-13).
Data as JSON: /api/errors/8df851c3fb87e2f6.
Report an issue: GitHub.