{"record":{"id":"2b73333e4827960f","repo":"calcom/cal.diy","slug":"provided-slotduration-is-not-one-of-the-possible","errorCode":null,"errorMessage":"Provided 'slotDuration' is not one of the possible lengths for the event type. The possible lengths for this variable length event type are: ${eventTypeMetadata.multipleDuration.join(\", \")}","messagePattern":"Provided 'slotDuration' is not one of the possible lengths for the event type\\. The possible lengths for this variable length event type are: (.+?)","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"apps/api/v2/src/modules/slots/slots-2024-09-04/services/slots.service.ts","lineNumber":225,"sourceCode":"    );\n\n    if (overlappingReservation) {\n      throw new UnprocessableEntityException(\n        `This time slot is already reserved by another user. Please choose a different time.`\n      );\n    }\n  }\n\n  validateSlotDuration(eventType: EventType, inputSlotDuration: number) {\n    const eventTypeMetadata = eventTypeMetadataSchema.parse(eventType.metadata);\n    if (!eventTypeMetadata?.multipleDuration) {\n      throw new BadRequestException(\n        \"You passed 'slotDuration' but this event type is not a variable length event type.\"\n      );\n    }\n\n    if (!eventTypeMetadata.multipleDuration.includes(inputSlotDuration)) {\n      throw new BadRequestException(\n        `Provided 'slotDuration' is not one of the possible lengths for the event type. The possible lengths for this variable length event type are: ${eventTypeMetadata.multipleDuration.join(\n          \", \"\n        )}`\n      );\n    }\n  }\n\n  async canSpecifyCustomReservationDuration(authUserId: number, eventType: EventType) {\n    if (eventType.userId) {\n      return await this.canSpecifyCustomReservationDurationIndividualEvent(authUserId, eventType.userId);\n    }\n    if (eventType.teamId) {\n      return await this.canSpecifyCustomReservationDurationTeamEvent(authUserId, eventType.teamId);\n    }\n    return false;\n  }\n\n  async canSpecifyCustomReservationDurationIndividualEvent(authUserId: number, eventTypeOwnerId: number) {","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/apps/api/v2/src/modules/slots/slots-2024-09-04/services/slots.service.ts#L207-L243","documentation":"Thrown by SlotsService.validateSlotDuration when reserving or updating a slot for a variable-length event type. Variable-length event types store their allowed durations as a number array in eventType.metadata.multipleDuration; the slotDuration you pass must be an element of that array or the request is rejected as a 400 BadRequest. The message dynamically lists the valid values so the client can correct the input.","triggerScenarios":"POST /v2/event-types/{eventTypeId}/slots or PATCH /v2/slots/{uid} with a body containing slotDuration: 20 on an event type whose metadata.multipleDuration is [15,30,45]. The event type IS variable-length (multipleDuration exists), so the earlier 'not a variable length event type' guard is skipped, but 20 is not in the array.","commonSituations":"A UI dropdown of durations is desynced from the event type's configured multipleDuration after an admin edited the event type. An integration hardcodes a duration (e.g. 30) that was later removed from the event type. A client caches the duration list and sends a stale value after the event type was updated.","solutions":["Fetch the event type first and read metadata.multipleDuration (exposed as lengthInMinutesOptions), then pass only a value present in that array.","If any valid duration is acceptable, omit slotDuration entirely so the service falls back to eventType.length.","Update the event type's metadata.multipleDuration to include the desired duration before reserving."],"exampleFix":"// before\nbody: { eventTypeId, slotStart, slotDuration: 20 }\n\n// after\nconst et = await api.getEventType(eventTypeId);\nconst allowed = et.lengthInMinutesOptions ?? [et.length];\nconst slotDuration = allowed.includes(20) ? 20 : et.length;\nbody: { eventTypeId, slotStart, slotDuration }","handlingStrategy":"validation","validationCode":"import type { EventType } from './types';\n\nfunction pickSlotDuration(\n  et: Pick<EventType, 'length' | 'lengthInMinutesOptions'>,\n  requested?: number\n): number | undefined {\n  if (requested === undefined) return undefined; // fall back to event type length\n  const allowed = et.lengthInMinutesOptions ?? [];\n  return allowed.includes(requested) ? requested : undefined;\n}\n\n// usage:\n// const slotDuration = pickSlotDuration(eventType, body.slotDuration);\n// if (body.slotDuration && slotDuration === undefined) { /* warn user */ }","typeGuard":"function isValidSlotDuration(\n  et: { multipleDuration?: number[]; length: number },\n  value: number\n): boolean {\n  const allowed = et.multipleDuration ?? [et.length];\n  return allowed.includes(value);\n}","tryCatchPattern":"try {\n  await api.reserveSlot({ eventTypeId, slotStart, slotDuration });\n} catch (e) {\n  if (e.status === 400 && /possible lengths/.test(e.message)) {\n    // parse allowed list from message, reprompt user to pick a valid duration\n  } else throw e;\n}","preventionTips":["Always derive the duration picker options from lengthInMinutesOptions on the fetched event type, never hardcode them.","When the event type is edited, invalidate any cached duration lists in the client.","Omit slotDuration when you want the event type's default length rather than guessing a value."],"tags":["validation","slots","event-type","api-v2","multiple-duration"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}