calcom/cal.diy · error · BadRequestException
Booking with bookingUid=${bookingUid} is not part of a recur
Error message
Booking with bookingUid=${bookingUid} is not part of a recurring booking. What it means
Thrown by getAllRecurringBookingsByIndividualUid when the booking identified by bookingUid has no recurringEventId — i.e. it is a standalone booking, not part of a recurring series. Triggered when cancelSubsequentBookings is requested on a non-recurring booking. BadRequestException (HTTP 400).
Source
Thrown at apps/api/v2/src/platform/bookings/2024-08-13/services/bookings.service.ts:938
arePlatformEmailsEnabled: bookingRequest.arePlatformEmailsEnabled,
platformClientId: bookingRequest.platformClientId,
platformCancelUrl: bookingRequest.platformCancelUrl,
platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
platformBookingUrl: bookingRequest.platformBookingUrl,
});
if ("cancelSubsequentBookings" in body && body.cancelSubsequentBookings) {
return this.getAllRecurringBookingsByIndividualUid(bookingUid, authUser);
}
return this.getBooking(bookingUid, authUser);
}
private async getAllRecurringBookingsByIndividualUid(bookingUid: string, authUser: AuthOptionalUser) {
const booking = await this.bookingsRepository.getByUid(bookingUid);
const recurringBookingUid = booking?.recurringEventId;
if (!recurringBookingUid) {
throw new BadRequestException(
`Booking with bookingUid=${bookingUid} is not part of a recurring booking.`
);
}
return await this.getBooking(recurringBookingUid, authUser);
}
async markAbsent(
bookingUid: string,
bookingOwnerId: number,
body: MarkAbsentBookingInput_2024_08_13,
userUuid: string
) {
const bodyTransformed = this.inputService.transformInputMarkAbsentBooking(body);
const bookingBefore = await this.bookingsRepository.getByUid(bookingUid);
if (!bookingBefore) {
throw new NotFoundException(`Booking with uid=${bookingUid} not found.`);View on GitHub (pinned to 176037d0af)
Solutions
- Only set cancelSubsequentBookings when the booking's recurringEventId is non-null.
- Fetch the booking first and branch: if recurringEventId present, allow bulk; else single cancel.
- Update event type to enable recurring schedules if bulk cancel is required.
Example fix
// before
await client.delete(`/v2/bookings/${uid}`, { data: { cancelSubsequentBookings: true } });
// after
const b = await client.get(`/v2/bookings/${uid}`);
await client.delete(`/v2/bookings/${uid}`, { data: { cancelSubsequentBookings: !!b.recurringEventId } }); Defensive patterns
Strategy: validation
Validate before calling
const b = await client.get(`/v2/bookings/${uid}`);
if (!b.recurringEventId) throw new Error('Booking is not recurring; cannot cancel subsequent'); Type guard
function isRecurring(b: { recurringEventId?: string | null }): boolean {
return !!b.recurringEventId;
} Try / catch
try { await client.delete(`/v2/bookings/${uid}`, { data: { cancelSubsequentBookings: true } }); }
catch (e) {
if (e.status === 400 && /not part of a recurring/i.test(e.message)) { /* retry without the flag */ }
else throw e;
} Prevention
- Check recurringEventId before enabling bulk options in UI
- Gate cancelSubsequentBookings on a recurring check
- Only expose 'cancel all' for recurring bookings
When it happens
Trigger: A cancel or fetch request with cancelSubsequentBookings=true (or equivalent recurring expansion) on a booking that is not a member of a recurring series.
Common situations: UI offers 'cancel all subsequent' for non-recurring bookings; logic assumes recurring based on event type but the booking was created as a single instance.
Related errors
- Team with slug ${body.teamSlug} not found
- Missing attendee phone number - it is required by the event
- Missing required booking field response: ${eventTypeBookingF
- Invalid option '${submittedValue}' for booking field '${even
- One or more invalid options for booking field '${eventTypeBo
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/acb80704e3870d74.
Report an issue: GitHub.