{"record":{"id":"8ccfa23866c62d0f","repo":"calcom/cal.diy","slug":"invalid-end-date","errorCode":null,"errorMessage":"Invalid end date","messagePattern":"Invalid end date","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"apps/api/v2/src/modules/slots/slots-2024-09-04/services/slots-input.service.ts","lineNumber":148,"sourceCode":"    }\n\n    const ISOStartTime = dateTime.toISO();\n    if (ISOStartTime === null) {\n      throw new BadRequestException(\"Invalid start date\");\n    }\n\n    return ISOStartTime;\n  }\n\n  private adjustEndTime(endTime: string) {\n    let dateTime = DateTime.fromISO(endTime, { zone: \"utc\" });\n    if (dateTime.hour === 0 && dateTime.minute === 0 && dateTime.second === 0) {\n      dateTime = dateTime.set({ hour: 23, minute: 59, second: 59 });\n    }\n\n    const ISOEndTime = dateTime.toISO();\n    if (ISOEndTime === null) {\n      throw new BadRequestException(\"Invalid end date\");\n    }\n\n    return ISOEndTime;\n  }\n}\n","sourceCodeStart":130,"sourceCodeEnd":154,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/apps/api/v2/src/modules/slots/slots-2024-09-04/services/slots-input.service.ts#L130-L154","documentation":"A NestJS BadRequestException (HTTP 400) from SlotsInputService_2024_09_04.adjustEndTime. Symmetric to the start-time guard: DateTime.fromISO(endTime, {zone:'utc'}).toISO() returned null, so the `end` query parameter is not a valid ISO datetime. The window end cannot be established.","triggerScenarios":"Calling GET /v2/slots/2024-09-04 with a malformed, empty, or non-ISO `end` parameter, or with `end` earlier than `start` in a way that produces an invalid window here (though start>end is caught later as a time-range error; this one is strictly about unparseable values).","commonSituations":"Reusing a date picker that returns 'MM/DD/YYYY'; sending a relative string like 'now+7d'; copy-paste introducing a stray space; the end being omitted and serialized as 'undefined'/'null'.","solutions":["Send `end` as a full ISO 8601 UTC string via new Date().toISOString().","Client-side validate: DateTime.fromISO(end, {zone:'utc'}).isValid === true.","Make sure end is strictly after start before firing the request.","Default a missing end to start + N days explicitly rather than passing an empty string."],"exampleFix":"// before\nfetch(`/v2/slots?start=${start}&end=${endPicker}`) // '09/04/2024'\n\n// after\nconst end = DateTime.fromJSDate(endPicker).toUTC().toISO();\nif (!end) throw new Error('bad end');\nfetch(`/v2/slots?start=${encodeURIComponent(start)}&end=${encodeURIComponent(end)}`);","handlingStrategy":"validation","validationCode":"import { DateTime } from 'luxon';\n\nfunction toValidEndISO(end: unknown, startISO: string): string {\n  if (typeof end !== 'string') throw new TypeError('end must be an ISO string');\n  const dt = DateTime.fromISO(end, { zone: 'utc' });\n  if (!dt.isValid) throw new RangeError(`Invalid end: ${dt.invalidReason} (${end})`);\n  if (dt.toMillis() <= DateTime.fromISO(startISO, { zone: 'utc' }).toMillis()) {\n    throw new RangeError('end must be after start');\n  }\n  return dt.toISO()!;\n}\nconst end = toValidEndISO(input.end, start);","typeGuard":"function isISODateAfter(v: unknown, minISO: string): v is string {\n  if (typeof v !== 'string') return false;\n  const dt = DateTime.fromISO(v, { zone: 'utc' });\n  return dt.isValid && dt.toMillis() > DateTime.fromISO(minISO, { zone: 'utc' }).toMillis();\n}","tryCatchPattern":"try {\n  await cal.slots.list({ ..., end });\n} catch (e) {\n  if (e instanceof HttpError && e.statusCode === 400 && /end/i.test(e.message)) {\n    throw new UserFacingError('Please pick a valid end date/time after the start.');\n  }\n  throw e;\n}","preventionTips":["Default end to start + N days explicitly rather than leaving it empty.","Validate end > start before the request.","Use ISO strings from a Date library, not user-typed formats.","Encode the value to survive URL transport."],"tags":["calcom-api","slots","bad-request","luxon","datetime","validation"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}