denoland/deno · error · TypeError
Delay cannot be greater than 30 days: received
Error message
Delay cannot be greater than 30 days: received ${delay} What it means
The KV queue's maximum delay is capped at 30 days (`maxQueueDelay = 30*24*60*60*1000` ms). `kv.enqueue(..., { delay })` with a larger value throws before touching the database, because the queue's scheduling horizon does not extend further.
Solutions
- Pass a relative duration of at most 2_592_000_000 ms (30 days)
- For longer horizons, enqueue a short-delay message that re-schedules itself when delivered, or store a due-date key and poll it
- Double-check the value is not an absolute `Date.now()`-based timestamp
Example fix
// before
await kv.enqueue(job, { delay: Date.now() + 60_000 }); // absolute ms -> throws
// after
await kv.enqueue(job, { delay: 60_000 }); // relative ms Defensive patterns
Strategy: validation
Validate before calling
const MAX_DELAY = 30 * 24 * 60 * 60 * 1000;
if (delay > MAX_DELAY) throw new Error("delay > 30 days; use self-rescheduling");
await kv.enqueue(msg, { delay }); Type guard
const isWithinQueueDelayCap = (d: number): boolean => Number.isFinite(d) && d >= 0 && d <= 30 * 24 * 60 * 60 * 1000;
Prevention
- Assert the value is a relative duration, not Date.now()-based
- Split horizons longer than 30 days into chained self-rescheduling messages
- Unit-test enqueue option builders at the 30-day boundary
When it happens
Trigger: `delay: 31*24*60*60*1000`; passing an absolute epoch timestamp such as `Date.now() + 60_000` (ms-since-epoch dwarfs the cap); miscalculated day-to-ms conversions (e.g. days multiplied by 1000 only).
Common situations: Long-horizon scheduled jobs (monthly reminders, expiring invitations); accidentally passing a timestamp instead of a duration; porting scheduler configs from systems that accept absolute dates.
Related errors
- Delay must be >= 0: received
- Delay cannot be NaN
- Invalid backoffSchedule, interval at index
- Invalid backoffSchedule, max
- expireIn must be a non-negative integer: received
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/97472e1eee0d2e41.
Report an issue: GitHub.
Appendix: source
Thrown at ext/kv/01_db.ts:71
const encodeCursor: (
selector: [Deno.KvKey | null, Deno.KvKey | null, Deno.KvKey | null],
boundaryKey: Deno.KvKey,
) => string = (selector, boundaryKey) =>
op_kv_encode_cursor(selector, boundaryKey);
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}`,
);
}View on GitHub (pinned to 9ad36f7a2c)