calcom/cal.diy · error · BadRequestException

Can't reschedule booking with uid=

Error message

Can't reschedule booking with uid=${bookingUid} because it has been cancelled and rescheduled already to booking with uid=${rescheduledTo?.uid}. You probably want to reschedule ${rescheduledTo?.uid} instead by passing it within the request URL.

What it means

Thrown by canRescheduleBooking when the booking is CANCELLED and the rescheduled flag is true — it was already rescheduled into a new booking. The service looks up the new booking via getByFromReschedule and returns its uid in the message so the caller can redirect. BadRequestException (HTTP 400).

Solutions

  1. Parse the rescheduledTo uid from the error message and re-issue the reschedule against that uid.
  2. Store the latest booking uid locally, updating it whenever a reschedule succeeds.
  3. Consume booking.updated/rescheduled webhooks to keep the active uid current.

Example fix

// before
await client.post(`/v2/bookings/${oldUid}/reschedule`, body);
// after
try { await client.post(`/v2/bookings/${oldUid}/reschedule`, body); }
catch (e) {
  const m = e.message.match(/reschedule ([a-z0-9]+)/i);
  if (m) await client.post(`/v2/bookings/${m[1]}/reschedule`, body);
  else throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

const b = await client.get(`/v2/bookings/${uid}`);
if (b.status === 'CANCELLED' && b.rescheduled) throw new Error(`Already rescheduled; use ${b.rescheduledToUid}`);

Type guard

function needsRedirect(b: { status: string; rescheduled?: boolean }): boolean {
  return b.status === 'CANCELLED' && !!b.rescheduled;
}

Try / catch

try { await client.post(`/v2/bookings/${uid}/reschedule`, body); }
catch (e) {
  if (e.status === 400) {
    const m = e.message.match(/reschedule ([a-z0-9]+)/i);
    if (m) { return client.post(`/v2/bookings/${m[1]}/reschedule`, body); }
  }
  throw e;
}

Prevention

When it happens

Trigger: Rescheduling a booking that was previously cancelled because it was rescheduled; the original uid is now superseded by the rescheduledTo uid.

Common situations: Client cached the old uid after a reschedule already occurred; webhook-driven retry hitting the superseded booking.

Related errors


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

Appendix: source

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

      return Object.assign(outputBooking, { isPlatformManagedUserBooking });
    } catch (error) {
      this.errorsBookingsService.handleBookingError(error, false);
    }
  }

  async canRescheduleBooking(bookingUid: string) {
    const booking = await this.bookingsRepository.getByUid(bookingUid);
    if (!booking) {
      throw new Error(`Booking with uid=${bookingUid} was not found in the database`);
    }
    if (booking.status === "CANCELLED" && !booking.rescheduled) {
      throw new BadRequestException(
        `Can't reschedule booking with uid=${bookingUid} because it has been cancelled. Please provide uid of a booking that is not cancelled.`
      );
    }
    if (booking.status === "CANCELLED" && booking.rescheduled) {
      const rescheduledTo = await this.bookingsRepository.getByFromReschedule(bookingUid);
      throw new BadRequestException(
        `Can't reschedule booking with uid=${bookingUid} because it has been cancelled and rescheduled already to booking with uid=${rescheduledTo?.uid}. You probably want to reschedule ${rescheduledTo?.uid} instead by passing it within the request URL.`
      );
    }
    return booking;
  }

  async shouldRescheduleIndividualSeat(
    bookingUid: string,
    isIndividualSeatReschedule: boolean,
    authUser: AuthOptionalUser
  ) {
    const booking = await this.bookingsRepository.getByUidWithUserIdAndSeatsReferencesCount(bookingUid);

    if (!booking) {
      throw new NotFoundException(`Booking with uid=${bookingUid} was not found in the database`);
    }

    const hasSeatsPresent = booking.seatsReferences.length > 0;

View on GitHub (pinned to 176037d0af)