calcom/cal.diy · error · BadRequestException
You passed 'slotDuration' but this event type is not a varia
Error message
You passed 'slotDuration' but this event type is not a variable length event type.
What it means
A NestJS BadRequestException (HTTP 400) from SlotsService_2024_09_04.validateSlotDuration. The caller passed slotDuration, but eventType.metadata.multipleDuration is absent/falsy. slotDuration is only valid for variable-length event types that declare a multipleDuration array in their metadata. A fixed-length event type rejects an explicit duration.
Source
Thrown at apps/api/v2/src/modules/slots/slots-2024-09-04/services/slots.service.ts:219
private async checkSlotOverlap(eventTypeId: number, startDate: string, endDate: string) {
const overlappingReservation = await this.slotsRepository.getOverlappingSlotReservation(
eventTypeId,
startDate,
endDate
);
if (overlappingReservation) {
throw new UnprocessableEntityException(
`This time slot is already reserved by another user. Please choose a different time.`
);
}
}
validateSlotDuration(eventType: EventType, inputSlotDuration: number) {
const eventTypeMetadata = eventTypeMetadataSchema.parse(eventType.metadata);
if (!eventTypeMetadata?.multipleDuration) {
throw new BadRequestException(
"You passed 'slotDuration' but this event type is not a variable length event type."
);
}
if (!eventTypeMetadata.multipleDuration.includes(inputSlotDuration)) {
throw new BadRequestException(
`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(
", "
)}`
);
}
}
async canSpecifyCustomReservationDuration(authUserId: number, eventType: EventType) {
if (eventType.userId) {
return await this.canSpecifyCustomReservationDurationIndividualEvent(authUserId, eventType.userId);
}
if (eventType.teamId) {View on GitHub (pinned to 176037d0af)
Solutions
- Only send slotDuration for event types whose metadata.multipleDuration is a non-empty array.
- Inspect the event type via GET /v2/event-types and branch on whether it is variable-length.
- For fixed-length event types, omit slotDuration and let eventType.length apply.
- On the client, gate the slotDuration field behind a 'variable length' flag.
Example fix
// before
fetch('/v2/slots/reserve', { body: JSON.stringify({ eventTypeId, slotStart, slotDuration: 30 }) });
// after — only include slotDuration for variable-length events
const body: any = { eventTypeId, slotStart };
if (eventType.metadata?.multipleDuration?.length) body.slotDuration = 30;
fetch('/v2/slots/reserve', { body: JSON.stringify(body) }); Defensive patterns
Strategy: validation
Validate before calling
function buildReserveBody(eventType: { metadata?: { multipleDuration?: number[] } | null }, slotStart: string, slotDuration?: number) {
const body: { eventTypeId?: number; slotStart: string; slotDuration?: number } = { slotStart };
if (eventType.metadata?.multipleDuration?.length && slotDuration != null) {
if (!eventType.metadata.multipleDuration.includes(slotDuration)) {
throw new RangeError(`slotDuration must be one of: ${eventType.metadata.multipleDuration.join(', ')}`);
}
body.slotDuration = slotDuration;
}
return body;
}
const body = buildReserveBody(eventType, slotStart, input.slotDuration); Type guard
function isVariableLengthEventType(et: { metadata?: { multipleDuration?: number[] } | null }): boolean {
return Array.isArray(et.metadata?.multipleDuration) && (et.metadata!.multipleDuration as number[]).length > 0;
} Try / catch
try {
await cal.slots.reserve({ eventTypeId, slotStart, slotDuration });
} catch (e) {
if (e instanceof HttpError && e.statusCode === 400 && /variable length/i.test(e.message)) {
// event type is fixed-length — retry without slotDuration
return cal.slots.reserve({ eventTypeId, slotStart });
}
throw e;
} Prevention
- Gate slotDuration behind a variable-length check on the event type.
- Only pass slotDuration values listed in metadata.multipleDuration.
- For fixed-length event types, omit slotDuration.
- Inspect event type metadata before building the reserve payload.
When it happens
Trigger: POST /v2/slots/reserve with a slotDuration field for an event type whose metadata does not include multipleDuration — i.e. a standard fixed-length event type. The DTO allows slotDuration optionally, so this is the runtime semantic check.
Common situations: Applying slotDuration uniformly across all event types in a generic booking flow; switching an event type from variable to fixed and leaving stale client code; copying a reserve payload from a variable event to a fixed one.
Related errors
- Event Type with ID=${input.eventTypeId} not found
- Invalid start date
- Invalid end date
- Invalid start date
- Invalid end date
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/c3b0082ff5d92bcd.
Report an issue: GitHub.