denoland/deno · error · TypeError
Invalid backoffSchedule, max
Error message
Invalid backoffSchedule, max ${maxQueueBackoffIntervals} intervals allowed What it means
`kv.enqueue(value, { backoffSchedule })` accepts at most 5 retry intervals (`maxQueueBackoffIntervals = 5`); the queue retries a failed message once per entry, and more than five retries have no backend support. A longer array is rejected up front with this TypeError.
Solutions
- Trim to the 5 most meaningful intervals (usually keep the early, fast retries and merge the tail)
- For more retries, re-enqueue on final failure with a fresh schedule
- Assert the length in a helper that builds backoff schedules
Example fix
// before
await kv.enqueue(job, { backoffSchedule: [1000, 5000, 10000, 30000, 60000, 120000] });
// after
await kv.enqueue(job, { backoffSchedule: [1000, 5000, 10000, 30000, 60000] }); Defensive patterns
Strategy: validation
Validate before calling
const MAX_INTERVALS = 5;
const backoffSchedule = rawSchedule.slice(0, MAX_INTERVALS);
await kv.enqueue(msg, { backoffSchedule }); Prevention
- Build backoff ladders through one helper that caps length at 5
- When porting retry configs, map the tail steps into a final re-enqueue instead of a 6th interval
- Keep a unit test asserting the schedule length
When it happens
Trigger: Passing six or more entries, e.g. `[1000, 5000, 10000, 30000, 60000, 120000]` — a common exponential ladder copied from another system.
Common situations: Porting retry ladders from job libraries (BullMQ, Sidekiq-style 6–8 step backoffs); schedules generated programmatically without a length bound.
Related errors
- Invalid backoffSchedule, interval at index
- Delay cannot be greater than 30 days: received
- Delay cannot be NaN
- Delay must be >= 0: received
- expireIn must be a non-negative integer: received
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/7a2accdcba9429ac.
Report an issue: GitHub.
Appendix: source
Thrown at ext/kv/01_db.ts:97
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;
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;View on GitHub (pinned to 9ad36f7a2c)