calcom/cal.diy · error · ConflictException
No more seats left at this seated booking.
Error message
No more seats left at this seated booking.
What it means
Thrown as a ConflictException (HTTP 409) when the underlying booking creation detects that a seated event type has no remaining seats. The service catches an error whose message equals 'booking_seats_full_error' (emitted by the core handleNewBooking/booking engine) and re-throws it with this user-facing message.
Source
Thrown at apps/api/v2/src/platform/bookings/2024-08-13/services/bookings.service.ts:547
}
const outputBooking = await this.outputService.getOutputCreateSeatedBooking(
databaseBooking,
booking.seatReferenceUid || "",
userIsEventTypeAdminOrOwner
);
return Object.assign(
outputBooking,
booking.userId
? {
isPlatformManagedUserBooking: booking.user?.isPlatformManaged ?? false,
}
: {}
);
} catch (error) {
if (error instanceof Error) {
if (error.message === "booking_seats_full_error") {
throw new ConflictException("No more seats left at this seated booking.");
}
}
throw error;
}
}
async getBooking(uid: string, authUser: AuthOptionalUser) {
const booking = await this.bookingsRepository.getByUidWithAttendeesWithBookingSeatAndUserAndEvent(uid);
const userIsEventTypeAdminOrOwner =
authUser && booking?.eventType
? await this.eventTypeAccessService.userIsEventTypeAdminOrOwner(authUser, booking.eventType)
: false;
if (booking) {
const isRecurring = !!booking.recurringEventId;
const isSeated = !!booking.eventType?.seatsPerTimeSlot;
if (isRecurring && !isSeated) {View on GitHub (pinned to 176037d0af)
Solutions
- Call the availability/slots endpoint immediately before booking to confirm remaining seats.
- On 409, refresh slot availability and offer the user an alternative time.
- Increase seatsPerTimeSlot on the event type if demand exceeds capacity.
Example fix
// before — book blindly
await client.post('/v2/bookings', body);
// after — check seats then book, retry on conflict
const slots = await client.get(`/v2/slots?eventTypeId=${eventTypeId}`);
if (slots[0].attendeesRemaining > 0) {
try { await client.post('/v2/bookings', body); }
catch (e) { if (e.status === 409) refreshSlots(); else throw e; }
} Defensive patterns
Strategy: retry
Validate before calling
const slot = await client.get(`/v2/slots?eventTypeId=${eventTypeId}&startTime=${start}`);
if ((slot.attendeesRemaining ?? 0) <= 0) throw new Error('No seats remaining'); Type guard
function hasSeats(slot: { attendeesRemaining?: number }): boolean {
return typeof slot.attendeesRemaining === 'number' && slot.attendeesRemaining > 0;
} Try / catch
try { await client.post('/v2/bookings', body); }
catch (e) {
if (e.status === 409 && /No more seats/i.test(e.message)) { /* refresh slots, offer alt time */ }
else throw e;
} Prevention
- Check seat availability right before booking
- Handle 409 by refreshing and retrying with a new slot
- Increase seatsPerTimeSlot if chronic contention
When it happens
Trigger: Creating or rescheduling a booking on a seated event type (seatsPerTimeSlot set) where all seats for that time slot are already booked — the new attendee would exceed capacity.
Common situations: Concurrent booking requests racing for the last seat; UI allowed selection of a slot that filled in the meantime; seatsPerTimeSlot reduced after bookings were made.
Related errors
- Booking with seatUid=${seatUid} was not found in the databas
- Invalid seatUid: this seat does not exist or has already bee
- Invalid seatUid: this seat does not belong to this booking.
- This time slot is already reserved by another user. Please c
- Team with slug ${body.teamSlug} not found
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/aa704bdba60ea700.
Report an issue: GitHub.