{"record":{"id":"289c9230d44dcf60","repo":"paperclipai/paperclip","slug":"invalid-expires-at-value-opts-expiresat","errorCode":null,"errorMessage":"Invalid --expires-at value: ${opts.expiresAt}","messagePattern":"Invalid --expires-at value: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/src/commands/client/token.ts","lineNumber":235,"sourceCode":"async function resolveAgent(api: { get<T>(path: string): Promise<T | null> }, companyId: string, agentRef: string): Promise<Agent> {\n  const trimmed = agentRef.trim();\n  if (!trimmed) throw new Error(\"Agent reference is required\");\n  if (/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(trimmed)) {\n    const agent = await api.get<Agent>(apiPath`/api/agents/${trimmed}`);\n    if (!agent || agent.companyId !== companyId) throw new Error(`Agent not found: ${agentRef}`);\n    return agent;\n  }\n  const query = new URLSearchParams({ companyId });\n  const agent = await api.get<Agent>(`${apiPath`/api/agents/${trimmed}`}?${query.toString()}`);\n  if (!agent || agent.companyId !== companyId) throw new Error(`Agent not found: ${agentRef}`);\n  return agent;\n}\n\nfunction resolveBoardKeyExpiresAt(opts: BoardTokenOptions): Date | null | undefined {\n  if (opts.neverExpires) return null;\n  if (opts.expiresAt?.trim()) {\n    const date = new Date(opts.expiresAt.trim());\n    if (!Number.isFinite(date.getTime())) throw new Error(`Invalid --expires-at value: ${opts.expiresAt}`);\n    return date;\n  }\n  if (opts.ttlDays?.trim()) {\n    const days = Number(opts.ttlDays);\n    if (!Number.isFinite(days) || days <= 0) throw new Error(`Invalid --ttl-days value: ${opts.ttlDays}`);\n    return new Date(Date.now() + Math.floor(days * 24 * 60 * 60 * 1000));\n  }\n  return undefined;\n}\n","sourceCodeStart":217,"sourceCodeEnd":245,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/cli/src/commands/client/token.ts#L217-L245","documentation":"Thrown by resolveBoardKeyExpiresAt (token.ts:235) when --expires-at is provided but new Date(value).getTime() is not finite, i.e. the string cannot be parsed into a valid date. Pre-empts sending a bad expiresAt to /api/board-api-keys.","triggerScenarios":"Passing --expires-at \"next week\", --expires-at \"2025-13-40\", or any non-ISO/non-RFC2822 string. The Date constructor returns Invalid Date and getTime() yields NaN.","commonSituations":"Locale-specific date formats, missing timezone, stray characters, or copy-pasting a human-readable expiry.","solutions":["Use an ISO 8601 timestamp: --expires-at 2025-12-31T23:59:59Z.","Prefer --ttl-days for relative expiries.","Validate the date string with `new Date(value)` in your shell before passing it."],"exampleFix":"// before\n--expires-at \"Dec 31\"\n// after\n--expires-at \"2025-12-31T00:00:00Z\"","handlingStrategy":"validation","validationCode":"function isValidExpiresAt(value: string | undefined): boolean {\n  if (!value?.trim()) return false;\n  return Number.isFinite(new Date(value.trim()).getTime());\n}\n\nif (opts.expiresAt && !isValidExpiresAt(opts.expiresAt)) {\n  console.error(`--expires-at \"${opts.expiresAt}\" is not a valid date. Use ISO 8601.`);\n  process.exit(1);\n}","typeGuard":"function isParsableDate(value: string): boolean {\n  return Number.isFinite(new Date(value).getTime());\n}","tryCatchPattern":null,"preventionTips":["Use ISO 8601 timestamps with explicit timezone (trailing Z or offset).","Prefer --ttl-days for relative expiries.","Test the date string with `new Date(value)` in your shell first."],"tags":["cli","argument-validation","date-parsing","board-keys"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}