{"record":{"id":"a5055721995d4828","repo":"calcom/cal.diy","slug":"could-not-adjust-timezone-for-slot-end-time-slot","errorCode":null,"errorMessage":"Could not adjust timezone for slot end time ${slot.time} with timezone ${timeZone}","messagePattern":"Could not adjust timezone for slot end time (.+?) with timezone (.+?)","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"apps/api/v2/src/modules/slots/slots-2024-09-04/services/slots-output.service.ts","lineNumber":136,"sourceCode":"    >((acc, [date, slots]) => {\n      const availableTimeSlots = slots.filter((slot) => !slot.away);\n      if (availableTimeSlots.length > 0) {\n        acc[date] = availableTimeSlots.map((slot) => {\n          if (timeZone) {\n            const start = DateTime.fromISO(slot.time, { zone: \"utc\" }).setZone(timeZone).toISO();\n            if (!start) {\n              throw new BadRequestException(\n                `Could not adjust timezone for slot ${slot.time} with timezone ${timeZone}`\n              );\n            }\n\n            const end = DateTime.fromISO(slot.time, { zone: \"utc\" })\n              .plus({ minutes: slotDuration })\n              .setZone(timeZone)\n              .toISO();\n\n            if (!end) {\n              throw new BadRequestException(\n                `Could not adjust timezone for slot end time ${slot.time} with timezone ${timeZone}`\n              );\n            }\n\n            if (!eventType?.seatsPerTimeSlot) {\n              return this.getAvailableRangeSlot(start, end);\n            }\n            return this.getAvailableRangeSlotSeated(\n              start,\n              end,\n              slot.attendees || 0,\n              eventType.seatsPerTimeSlot ?? undefined,\n              slot.bookingUid\n            );\n          } else {\n            const start = DateTime.fromISO(slot.time, { zone: \"utc\" }).toISO();\n            const end = DateTime.fromISO(slot.time, { zone: \"utc\" }).plus({ minutes: slotDuration }).toISO();\n","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/apps/api/v2/src/modules/slots/slots-2024-09-04/services/slots-output.service.ts#L118-L154","documentation":"A NestJS BadRequestException (HTTP 400) from SlotsOutputService_2024_09_04.getAvailableRangeSlots — the end-time conversion branch. The slot end (slot.time + slotDuration minutes) converted to the target timezone returned null from toISO(). Distinguished from 165 because the start conversion succeeded but the end (after plus({minutes: slotDuration})) failed.","triggerScenarios":"GET /v2/slots with format=range and a timeZone where the start converts but the computed end crosses into an invalid instant — in practice this fires when slotDuration is undefined/NaN producing an invalid DateTime, or when slot.time itself is borderline and the addition overflows luxon's representable range.","commonSituations":"Event type has no length and no duration passed (slotDuration = undefined → plus undefined minutes → invalid); duration query param coerced to NaN; extreme durations; DST gap near the slot combined with an unusual zone.","solutions":["Always pass an explicit duration query param for range requests when the event type length may be null.","Validate slotDuration is a finite positive integer before relying on it.","Validate timeZone as in 164/165.","If the event type is non-variable, ensure eventType.length is configured."],"exampleFix":"// before\nfetch(`/v2/slots?format=range&eventTypeSlug=...&timeZone=${tz}`) // no duration, ET length null\n\n// after\nfetch(`/v2/slots?format=range&eventTypeSlug=...&duration=30&timeZone=${encodeURIComponent(tz)}`);","handlingStrategy":"validation","validationCode":"import { DateTime } from 'luxon';\n\nfunction assertRangeParams(duration: unknown, tz: unknown) {\n  if (duration !== undefined) {\n    const d = Number(duration);\n    if (!Number.isFinite(d) || d <= 0) throw new RangeError('duration must be a positive number of minutes');\n  }\n  if (tz !== undefined && (typeof tz !== 'string' || !DateTime.now().setZone(tz).isValid)) {\n    throw new RangeError(`Unsupported timeZone: ${tz}`);\n  }\n}\nassertRangeParams(input.duration, input.timeZone);","typeGuard":"function isPositiveFiniteMinutes(v: unknown): v is number {\n  return typeof v === 'number' && Number.isFinite(v) && v > 0;\n}","tryCatchPattern":"try {\n  await cal.slots.list({ format: 'range', duration, ..., timeZone });\n} catch (e) {\n  if (e instanceof HttpError && e.statusCode === 400 && /end time|timezone/i.test(e.message)) {\n    // retry with explicit duration or without timeZone\n    return cal.slots.list({ format: 'range', duration: eventType.length, ... /* no tz */ });\n  }\n  throw e;\n}","preventionTips":["Always pass an explicit duration for range requests on event types whose length may be null.","Validate the timezone as IANA before sending.","Reject NaN/Infinity/negative durations client-side.","Confirm eventType.length is set before relying on the default."],"tags":["calcom-api","slots","bad-request","luxon","timezone","range-format","duration"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}