{"record":{"id":"589bd7827614aa82","repo":"nextauthjs/next-auth","slug":"option-expires-is-invalid-options-expires","errorCode":null,"errorMessage":"option expires is invalid: ${options.expires}","messagePattern":"option expires is invalid: (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/core/src/lib/vendored/cookie.ts","lineNumber":303,"sourceCode":"    }\n\n    str += \"; Domain=\" + options.domain\n  }\n\n  if (options.path) {\n    if (!pathValueRegExp.test(options.path)) {\n      throw new TypeError(`option path is invalid: ${options.path}`)\n    }\n\n    str += \"; Path=\" + options.path\n  }\n\n  if (options.expires) {\n    if (\n      !isDate(options.expires) ||\n      !Number.isFinite(options.expires.valueOf())\n    ) {\n      throw new TypeError(`option expires is invalid: ${options.expires}`)\n    }\n\n    str += \"; Expires=\" + options.expires.toUTCString()\n  }\n\n  if (options.httpOnly) {\n    str += \"; HttpOnly\"\n  }\n\n  if (options.secure) {\n    str += \"; Secure\"\n  }\n\n  if (options.partitioned) {\n    str += \"; Partitioned\"\n  }\n\n  if (options.priority) {","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/nextauthjs/next-auth/blob/a1a16a5a7780488c7449feece410033f445d0b31/packages/core/src/lib/vendored/cookie.ts#L285-L321","documentation":"serialize() requires the `expires` option, when provided, to be a real Date object with a finite time value. If it is not a Date instance (isDate fails) or its valueOf() is NaN/Infinity (an Invalid Date), a TypeError is thrown. This guards against invalid dates silently producing 'Expires=Invalid Date' in the header.","triggerScenarios":"Passing expires: new Date('not-a-date') (Invalid Date); passing a date string like '2026-01-01' instead of a Date; passing a number timestamp; passing null/undefined-like truthy junk; a Date computed from bad input such as new Date(undefined).","commonSituations":"Parsing user-supplied expiry dates without validation; jwt/session libs returning string timestamps; JSON round-tripping Dates (they come back as strings); arithmetic mistakes that yield NaN (e.g. new Date(Date.now() + ttl) where ttl is undefined).","solutions":["Pass an actual Date object with a valid value: new Date(Date.now() + 7*24*3600*1000)","If you have a timestamp number, wrap it: new Date(timestamp)","Check validity before calling: d instanceof Date && Number.isFinite(d.valueOf())","If the value may be a string, parse it first and verify it is not Invalid Date"],"exampleFix":"// before\nserialize('sid', val, { expires: payload.exp }) // number from JWT\n// after\nserialize('sid', val, { expires: new Date(payload.exp * 1000) })","handlingStrategy":"type-guard","validationCode":"function isValidExpires(v) {\n  return v instanceof Date && Number.isFinite(v.valueOf())\n}\nif (opts.expires && !isValidExpires(opts.expires)) throw new TypeError(`option expires is invalid: ${opts.expires}`)","typeGuard":"function isFiniteDate(v: unknown): v is Date {\n  return v instanceof Date && Number.isFinite(v.valueOf())\n}","tryCatchPattern":"let cookie\ntry {\n  cookie = serialize('sid', val, { expires })\n} catch (err) {\n  if (err instanceof TypeError && err.message.startsWith('option expires is invalid')) {\n    throw new SessionError(`Invalid expiry ${String(expires)} — pass a valid Date`)\n  }\n  throw err\n}","preventionTips":["Always construct Date objects from numeric timestamps, not raw strings","After new Date(x), assert Number.isFinite(d.valueOf()) before using it","Remember JSON serialization turns Dates into strings — re-parse on ingest","Compute expiries with explicit numeric TTLs to avoid NaN from undefined variables"],"tags":["cookie","validation","typeerror","date","serialize"],"backgroundTag":"invalid-cookie-attribute","analyzedSha":"a1a16a5a7780488c7449feece410033f445d0b31","analyzedAt":"2026-08-28T21:52:38.200Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}