denoland/deno · error · TypeError
Delay cannot be NaN
Error message
Delay cannot be NaN
What it means
The final check in validateQueueDelay: delay must not be NaN. NaN arises from parsing garbage ('parseInt("soon")'), arithmetic on undefined (undefined - Date.now()), or JSON payloads with null coerced oddly. Note the checks are ordered: NaN passes the < 0 and > max comparisons as false and is only caught by the explicit NumberIsNaN test.
Source
Thrown at ext/kv/01_db.ts:76
async function openKv(path: string) {
const rid = await op_kv_database_open(path);
return new Kv(rid, kvSymbol);
}
const maxQueueDelay = 30 * 24 * 60 * 60 * 1000;
function validateQueueDelay(delay: number) {
if (delay < 0) {
throw new TypeError(`Delay must be >= 0: received ${delay}`);
}
if (delay > maxQueueDelay) {
throw new TypeError(
`Delay cannot be greater than 30 days: received ${delay}`,
);
}
if (NumberIsNaN(delay)) {
throw new TypeError("Delay cannot be NaN");
}
}
function validateExpireIn(expireIn: number | undefined) {
if (expireIn === undefined) return;
// Reject NaN, Infinity, fractional and negative values. A non-finite
// expireIn otherwise reaches the native layer and overflows when computing
// the absolute expiry, panicking the process.
if (!NumberIsInteger(expireIn) || expireIn < 0) {
throw new TypeError(
`expireIn must be a non-negative integer: received ${expireIn}`,
);
}
}
const maxQueueBackoffIntervals = 5;
const maxQueueBackoffInterval = 60 * 60 * 1000;
View on GitHub (pinned to 89f33cbef2)
Solutions
- Validate/coerce before calling: const d = Number(delay); if (!Number.isFinite(d)) throw new Error('bad delay').
- Default missing values explicitly: const delay = opts.delay ?? 0.
- Strip units from config values or parse strictly (Number('500') not parseInt('500ms')).
Example fix
// before
const delay = config.waitMs - Date.now(); // config.waitMs undefined -> NaN
await kv.enqueue(job, { delay });
// after
const delay = Math.max(0, (config.waitMs ?? Date.now()) - Date.now());
await kv.enqueue(job, { delay }); Defensive patterns
Strategy: validation
Validate before calling
const delay = Number(opts.delay ?? 0);
if (!Number.isFinite(delay)) throw new Error(`invalid delay: ${opts.delay}`);
await kv.enqueue(job, { delay }); Type guard
function isFiniteNonNegative(n: unknown): n is number { return typeof n === "number" && Number.isFinite(n) && n >= 0; } Prevention
- Default optional numeric options explicitly (?? 0), don't do arithmetic on undefined.
- Parse env/config numbers with Number() and reject NaN at the boundary.
- Validate untrusted JSON numerics before passing them to KV.
When it happens
Trigger: kv.enqueue(msg, { delay: undefined - Date.now() }); delay: Number.parseInt(process.env.DELAY_MS, 10) with a non-numeric env var; delay: NaN from JSON.parse of a missing field defaulted incorrectly; delay: +"1e3 ms" parse failures.
Common situations: Optional config omitted then used in arithmetic; environment variables with units ('500ms') fed to parseInt; schema-less input payloads; defaulting with || where 0 was intended.
Related errors
- Delay must be >= 0: received ${delay}
- Invalid backoffSchedule, interval at index ${i} is invalid
- Delay cannot be greater than 30 days: received ${delay}
- expireIn must be a non-negative integer: received ${expireIn
- Invalid backoffSchedule, max ${maxQueueBackoffIntervals} int
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/5accd80f38700bbf.
Report an issue: GitHub.