denoland/deno · error · TypeError
Invalid backoffSchedule, interval at index ${i} is invalid
Error message
Invalid backoffSchedule, interval at index ${i} is invalid What it means
Each element of kv.enqueue's backoffSchedule must satisfy: interval >= 0, interval <= 60 * 60 * 1000 (1 hour, maxQueueBackoffInterval), and not NaN. The per-element check reports the first offending index so you can locate the bad value.
Source
Thrown at ext/kv/01_db.ts:107
}
}
const maxQueueBackoffIntervals = 5;
const maxQueueBackoffInterval = 60 * 60 * 1000;
function validateBackoffSchedule(backoffSchedule: number[]) {
if (backoffSchedule.length > maxQueueBackoffIntervals) {
throw new TypeError(
`Invalid backoffSchedule, max ${maxQueueBackoffIntervals} intervals allowed`,
);
}
for (let i = 0; i < backoffSchedule.length; ++i) {
const interval = backoffSchedule[i];
if (
interval < 0 || interval > maxQueueBackoffInterval ||
NumberIsNaN(interval)
) {
throw new TypeError(
`Invalid backoffSchedule, interval at index ${i} is invalid`,
);
}
}
}
interface RawKvEntry {
key: Deno.KvKey;
value: RawValue;
versionstamp: string;
}
type RawValue = {
kind: "v8";
value: Uint8Array;
} | {
kind: "bytes";
value: Uint8Array;View on GitHub (pinned to 89f33cbef2)
Solutions
- Clamp each interval: backoffSchedule.map((i) => Math.min(Math.max(0, i), 3600000)) after validating they are numbers.
- Cap exponential generation so the last step stays <= 1h.
- Validate the array before enqueue: every element Number.isInteger-ish, finite, in [0, 3600000].
Example fix
// before
const backoffSchedule = [100, 1000, 10000, 100000, 1000000, 7200000]; // 6th > 1h
await kv.enqueue(job, { backoffSchedule });
// after
const backoffSchedule = [100, 1000, 10000, 100000, 3600000].map((i) =>
Math.min(Math.max(0, i), 60 * 60 * 1000)
);
await kv.enqueue(job, { backoffSchedule }); Defensive patterns
Strategy: validation
Validate before calling
const MAX_MS = 60 * 60 * 1000;
const backoffSchedule = rawBackoff
.map((i) => Math.floor(Number(i)))
.filter((i) => Number.isFinite(i) && i >= 0)
.map((i) => Math.min(i, MAX_MS))
.slice(0, 5);
await kv.enqueue(job, { backoffSchedule }); Type guard
function isCleanBackoffSchedule(arr: unknown): arr is number[] { const MAX = 60 * 60 * 1000; return Array.isArray(arr) && arr.every((i) => typeof i === "number" && !Number.isNaN(i) && i >= 0 && i <= MAX); } Prevention
- Clamp every interval to [0, 3600000] ms.
- Keep intervals as validated numbers - never strings or undefined from JSON.
- Cap exponential backoff generation so the last step stays under one hour.
When it happens
Trigger: backoffSchedule: [100, -500, 1000] with a negative entry; [1000, 7200000] exceeding one hour; [Number('soon')] or [undefined] coercing to NaN; schedules expressed in seconds (e.g. 86400) being interpreted as ms is fine but the reverse - ms values like 3600001 - trip the cap; entries from JSON strings.
Common situations: Exponential backoff loops exceeding 1h at later steps (2^22+ ms); retry policies copied from cloud SDKs allowing day-long waits; sign errors in computed intervals; unvalidated user-configured retry arrays.
Related errors
- Invalid backoffSchedule, max ${maxQueueBackoffIntervals} int
- Delay must be >= 0: received ${delay}
- Delay cannot be NaN
- Delay cannot be greater than 30 days: received ${delay}
- expireIn must be a non-negative integer: received ${expireIn
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/481f2a29c698a72b.
Report an issue: GitHub.