{"record":{"id":"1bf0e1bd8afe12f6","repo":"calcom/cal.diy","slug":"invalid-datestring-format-expected-format-iso8061","errorCode":null,"errorMessage":"Invalid datestring format. Expected format(ISO8061): 2025-04-12T13:17:56.324Z. Received: ${value}","messagePattern":"Invalid datestring format\\. Expected format\\(ISO8061\\): 2025-04-12T13:17:56\\.324Z\\. Received: (.+?)","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"warning","filePath":"apps/api/v2/src/platform/schedules/schedules_2024_04_15/inputs/create-availability.input.ts","lineNumber":30,"sourceCode":"  @IsDate()\n  @Transform(({ value, key }: TransformFnParams) => transformStringToDate(value, key))\n  startTime!: Date;\n\n  @IsDate()\n  @Transform(({ value, key }: TransformFnParams) => transformStringToDate(value, key))\n  endTime!: Date;\n}\n\nfunction transformStringToDate(value: string, key: string): Date {\n  if (!value) {\n    throw new BadRequestException(\n      `Missing ${key}. Expected value is in ISO8061 format e.g. 2025-0412T13:17:56.324Z`\n    );\n  }\n\n  const dateTimeParts = value.split(\"T\");\n  if (dateTimeParts.length !== 2) {\n    throw new BadRequestException(\n      `Invalid datestring format. Expected format(ISO8061): 2025-04-12T13:17:56.324Z. Received: ${value}`\n    );\n  }\n\n  const timePart = dateTimeParts[1].split(\".\")[0]; // Removes milliseconds\n  const parts = timePart.split(\":\");\n\n  if (parts.length !== 3) {\n    throw new BadRequestException(\n      `Invalid time format. Expected format(ISO8061): 2025-0412T13:17:56.324Z. Received: ${value}`\n    );\n  }\n  const [hours, minutes, seconds] = parts.map(Number);\n\n  if (hours < 0 || hours > 23) {\n    throw new BadRequestException(`Invalid ${key} hours. Expected value between 0 and 23`);\n  }\n","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/apps/api/v2/src/platform/schedules/schedules_2024_04_15/inputs/create-availability.input.ts#L12-L48","documentation":"Thrown by transformStringToDate when the provided time string is non-empty but does not contain the 'T' separator that separates the date portion from the time portion in ISO 8601 format. The function splits on 'T' and expects exactly two parts; any other result triggers HTTP 400. Note the error message itself contains typos ('ISO8061' should be 'ISO8601' and '2025-0412' is missing a hyphen).","triggerScenarios":"Sending a date-only string like '2025-04-12' without a time component; sending a space-separated datetime like '2025-04-12 09:00:00' instead of 'T'; sending a Unix timestamp or other non-ISO format.","commonSituations":"Client uses date-fns format() without including time; frontend date picker returns only the date portion; locale-specific formatting uses a space instead of 'T'; sending a date string from a different API that uses a different separator.","solutions":["Format startTime and endTime as full ISO 8601 strings with a 'T' separator: '2025-04-12T09:00:00.000Z'.","Use JavaScript's toISOString() on a Date object to guarantee the correct format.","If using date-fns, use format(date, \"yyyy-MM-dd'T'HH:mm:ss.SSSxxx\") or simply date.toISOString()."],"exampleFix":"// before\n\"startTime\": \"2025-04-12 09:00:00\"\n// after\n\"startTime\": new Date('2025-04-12T09:00:00').toISOString()","handlingStrategy":"validation","validationCode":"function toISO8601(date: Date): string {\n  const iso = date.toISOString();\n  // Verify it contains a 'T' separator\n  if (!iso.includes('T')) {\n    throw new Error(`Invalid ISO format: ${iso}`);\n  }\n  return iso;\n}\n\n// Ensure all time values pass through this before the API call\navailability.startTime = toISO8601(new Date(2025, 3, 12, 9, 0, 0));","typeGuard":"function isValidISODateString(value: string): boolean {\n  // Must contain 'T' separator and be parseable\n  if (!value.includes('T')) return false;\n  const d = new Date(value);\n  return !isNaN(d.getTime());\n}","tryCatchPattern":"try {\n  await api.post('/v2/schedules', payload);\n} catch (error) {\n  if (error.response?.status === 400 && error.response.data.message?.includes('Invalid datestring format')) {\n    // Reformat the time string to include 'T' separator and retry\n    console.error('Date string missing T separator:', error.response.data.message);\n  }\n  throw error;\n}","preventionTips":["Always use Date.prototype.toISOString() to generate time strings — it guarantees the 'T' separator.","Never construct ISO date strings manually or with locale-aware formatters.","Validate date strings with a regex before sending: /^\\d{4}-\\d{2}-\\d{2}T.+/.","Test with multiple timezone inputs to ensure consistent 'T'-separated output."],"tags":["validation","date-format","input","schedules","iso8601"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}