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

  1. Call the availability/slots endpoint immediately before booking to confirm remaining seats.
  2. On 409, refresh slot availability and offer the user an alternative time.
  3. 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

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


AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12). Data as JSON: /api/errors/aa704bdba60ea700. Report an issue: GitHub.