calcom/cal.diy · error · BadRequestException

Invalid seatUid: this seat does not belong to this booking.

Error message

Invalid seatUid: this seat does not belong to this booking.

What it means

Thrown by cancelBooking when the seated-cancellation body resolves a seat, but the seat's parent booking uid does not match the bookingUid in the request path/body. BadRequestException (HTTP 400). This prevents cancelling a seat under the wrong booking.

Source

Thrown at apps/api/v2/src/platform/bookings/2024-08-13/services/bookings.service.ts:910

  }

  async cancelBooking(
    request: Request,
    bookingUid: string,
    body: CancelBookingInput,
    authUser: AuthOptionalUser
  ) {
    if (this.inputService.isCancelSeatedBody(body)) {
      const seat = await this.bookingSeatRepository.getByReferenceUid(body.seatUid);

      if (!seat) {
        throw new BadRequestException(
          "Invalid seatUid: this seat does not exist or has already been cancelled."
        );
      }

      if (seat && bookingUid !== seat.booking.uid) {
        throw new BadRequestException("Invalid seatUid: this seat does not belong to this booking.");
      }
    }

    const bookingRequest = await this.inputService.createCancelBookingRequest(request, bookingUid, body);
    const res = await handleCancelBooking({
      bookingData: bookingRequest.body,
      userId: bookingRequest.userId,
      userUuid: authUser?.uuid,
      actionSource: "API_V2",
      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);

View on GitHub (pinned to 176037d0af)

Solutions

  1. Always pair the seatUid with the bookingUid obtained from the same booking detail response.
  2. Fetch the booking and read seat.booking.uid to align the two values before cancelling.
  3. Validate seatUid ownership client-side: assert seat belongs to the booking in the URL.

Example fix

// before
await client.delete(`/v2/bookings/${bookingA}`, { data: { seatUid: seatFromBookingB } });
// after
const seat = booking.seats.find(s => s.seatUid === targetSeatUid);
await client.delete(`/v2/bookings/${seat.bookingUid}`, { data: { seatUid: seat.seatUid } });
Defensive patterns

Strategy: validation

Validate before calling

const booking = await client.get(`/v2/bookings/${uid}`);
const seat = booking.seats?.find(s => s.seatUid === body.seatUid);
if (!seat || seat.bookingUid !== uid) throw new Error('seatUid does not belong to this booking');

Type guard

function seatBelongsToBooking(seat: { bookingUid: string } | undefined, uid: string): boolean {
  return !!seat && seat.bookingUid === uid;
}

Try / catch

try { await client.delete(`/v2/bookings/${uid}`, { data: { seatUid } }); }
catch (e) {
  if (e.status === 400 && /does not belong to this booking/i.test(e.message)) { /* refetch seats, correct pairing */ }
  else throw e;
}

Prevention

When it happens

Trigger: Cancelling a seat where body.seatUid belongs to booking A but the request targets booking B (mismatched path uid and seat uid).

Common situations: Stale pairing of bookingUid and seatUid in client state; copy-paste error; seat reused across bookings (data integrity issue).

Related errors


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