{"record":{"id":"481f2a29c698a72b","repo":"denoland/deno","slug":"invalid-backoffschedule-interval-at-index-i-is","errorCode":null,"errorMessage":"Invalid backoffSchedule, interval at index ${i} is invalid","messagePattern":"Invalid backoffSchedule, interval at index (.+?) is invalid","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/kv/01_db.ts","lineNumber":107,"sourceCode":"  }\n}\n\nconst maxQueueBackoffIntervals = 5;\nconst maxQueueBackoffInterval = 60 * 60 * 1000;\n\nfunction validateBackoffSchedule(backoffSchedule: number[]) {\n  if (backoffSchedule.length > maxQueueBackoffIntervals) {\n    throw new TypeError(\n      `Invalid backoffSchedule, max ${maxQueueBackoffIntervals} intervals allowed`,\n    );\n  }\n  for (let i = 0; i < backoffSchedule.length; ++i) {\n    const interval = backoffSchedule[i];\n    if (\n      interval < 0 || interval > maxQueueBackoffInterval ||\n      NumberIsNaN(interval)\n    ) {\n      throw new TypeError(\n        `Invalid backoffSchedule, interval at index ${i} is invalid`,\n      );\n    }\n  }\n}\n\ninterface RawKvEntry {\n  key: Deno.KvKey;\n  value: RawValue;\n  versionstamp: string;\n}\n\ntype RawValue = {\n  kind: \"v8\";\n  value: Uint8Array;\n} | {\n  kind: \"bytes\";\n  value: Uint8Array;","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/kv/01_db.ts#L89-L125","documentation":"Each entry of `backoffSchedule` must satisfy `0 <= interval <= 60*60*1000` ms (one hour, `maxQueueBackoffInterval`) and must not be NaN. `validateBackoffSchedule` walks the array and names the first offending index in the message; the enqueue is rejected before any op runs.","triggerScenarios":"`backoffSchedule: [1000, -5000]`; `[1000, 7_200_000]` (2 hours exceeds the 1-hour cap); an entry computed as NaN from missing config or bad parsing.","commonSituations":"Unit mistakes (seconds used where ms is expected); long idle-retry ladders that exceed an hour per step; intervals derived from external config that can be absent.","solutions":["Clamp each entry: `schedule.map((i) => Math.min(3_600_000, Math.max(0, Math.round(i))))`","Verify millisecond units and drop/merge intervals above one hour","Filter out non-finite entries before enqueueing"],"exampleFix":"// before\nawait kv.enqueue(job, { backoffSchedule: [1000, 5, 7200000] }); // seconds & 2h -> throws\n\n// after\nawait kv.enqueue(job, { backoffSchedule: [1000, 5000, 3_600_000] }); // ms, <= 1h","handlingStrategy":"validation","validationCode":"const MAX_MS = 60 * 60 * 1000;\nconst backoffSchedule = rawSchedule\n  .filter((i) => Number.isFinite(i))\n  .map((i) => Math.min(MAX_MS, Math.max(0, Math.round(i))));\nawait kv.enqueue(msg, { backoffSchedule });","typeGuard":"const isValidBackoffInterval = (v: unknown): v is number =>\n  typeof v === \"number\" && Number.isFinite(v) && v >= 0 && v <= 60 * 60 * 1000;","tryCatchPattern":null,"preventionTips":["Express intervals in milliseconds and clamp each to [0, 3600000]","Drop or merge hourly-plus retries — the queue rejects them","Filter non-finite entries from config-derived schedules before enqueue"],"tags":["kv","deno-kv","queue","retry","backoff","validation"],"backgroundTag":"retry-backoff-invalid","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}