{"record":{"id":"5accd80f38700bbf","repo":"denoland/deno","slug":"delay-cannot-be-nan","errorCode":null,"errorMessage":"Delay cannot be NaN","messagePattern":"Delay cannot be NaN","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/kv/01_db.ts","lineNumber":76,"sourceCode":"\nasync function openKv(path: string) {\n  const rid = await op_kv_database_open(path);\n  return new Kv(rid, kvSymbol);\n}\n\nconst maxQueueDelay = 30 * 24 * 60 * 60 * 1000;\n\nfunction validateQueueDelay(delay: number) {\n  if (delay < 0) {\n    throw new TypeError(`Delay must be >= 0: received ${delay}`);\n  }\n  if (delay > maxQueueDelay) {\n    throw new TypeError(\n      `Delay cannot be greater than 30 days: received ${delay}`,\n    );\n  }\n  if (NumberIsNaN(delay)) {\n    throw new TypeError(\"Delay cannot be NaN\");\n  }\n}\n\nfunction validateExpireIn(expireIn: number | undefined) {\n  if (expireIn === undefined) return;\n  // Reject NaN, Infinity, fractional and negative values. A non-finite\n  // expireIn otherwise reaches the native layer and overflows when computing\n  // the absolute expiry, panicking the process.\n  if (!NumberIsInteger(expireIn) || expireIn < 0) {\n    throw new TypeError(\n      `expireIn must be a non-negative integer: received ${expireIn}`,\n    );\n  }\n}\n\nconst maxQueueBackoffIntervals = 5;\nconst maxQueueBackoffInterval = 60 * 60 * 1000;\n","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/kv/01_db.ts#L58-L94","documentation":"The third check in `validateQueueDelay`: comparisons against NaN are false, so NaN slips past the `< 0` and `> max` tests and is caught explicitly with this dedicated message. `kv.enqueue(..., { delay: NaN })` therefore throws before the op runs.","triggerScenarios":"`delay: undefined * 1000` (undefined config multiplied); `Number.parseInt('soon')`-style parse failures; arithmetic on missing option values such as `options.delayMs * multiplier` where `delayMs` is undefined.","commonSituations":"Optional config that arrives as undefined; parsing user-supplied delay input; computing a delay from a missing field on an object.","solutions":["Default missing values: `delay ?? 0`","Validate with `Number.isFinite(delay)` before the enqueue","Fix the upstream computation that produced the NaN"],"exampleFix":"// before\nawait kv.enqueue(job, { delay: opts.delayMs * factor }); // NaN when delayMs undefined\n\n// after\nconst delay = Number.isFinite(opts.delayMs) ? opts.delayMs * factor : 0;\nawait kv.enqueue(job, { delay });","handlingStrategy":"validation","validationCode":"if (!Number.isFinite(delay)) {\n  throw new Error(`delay is not a finite number: ${delay}`);\n}\nawait kv.enqueue(msg, { delay });","typeGuard":"const isFiniteNumber = (v: unknown): v is number =>\n  typeof v === \"number\" && Number.isFinite(v);","tryCatchPattern":null,"preventionTips":["Default optional delay config with `?? 0` before arithmetic","Validate parsed user input with Number.isFinite, not truthiness","Run arithmetic only on values proven numeric"],"tags":["kv","deno-kv","queue","nan","validation"],"backgroundTag":"nan-argument","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"}