{"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":"validation","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/89f33cbef296a2b287f323d42de54c871fa69c77/ext/kv/01_db.ts#L89-L125","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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]."],"exampleFix":"// before\nconst backoffSchedule = [100, 1000, 10000, 100000, 1000000, 7200000]; // 6th > 1h\nawait kv.enqueue(job, { backoffSchedule });\n\n// after\nconst backoffSchedule = [100, 1000, 10000, 100000, 3600000].map((i) =>\n  Math.min(Math.max(0, i), 60 * 60 * 1000)\n);\nawait kv.enqueue(job, { backoffSchedule });","handlingStrategy":"validation","validationCode":"const MAX_MS = 60 * 60 * 1000;\nconst backoffSchedule = rawBackoff\n  .map((i) => Math.floor(Number(i)))\n  .filter((i) => Number.isFinite(i) && i >= 0)\n  .map((i) => Math.min(i, MAX_MS))\n  .slice(0, 5);\nawait kv.enqueue(job, { backoffSchedule });","typeGuard":"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); }","tryCatchPattern":null,"preventionTips":["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."],"tags":["kv","queue","retry","backoff","validation"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}