calcom/cal.diy · error · HttpException
httpError?.message ?? errMsg
Error message
httpError?.message ?? errMsg
What it means
This is the message expression inside handleBookingErrors when the caught error is an instance of HttpError (Cal.com's domain error class with statusCode, message, url, method fields). The handler wraps it into a NestJS HttpException, preserving the original statusCode (defaulting to 500) and message (defaulting to the contextual errMsg like 'Error while creating recurring booking.'). It surfaces the upstream service's HTTP error to the API v2 caller.
Source
Thrown at apps/api/v2/src/platform/bookings/2024-04-15/controllers/bookings.controller.ts:593
if (requestBody?.responses?.guests?.length) {
requestBody.responses.guests = await this.platformBookingsService.getPlatformAttendeesEmails(
requestBody.responses.guests,
oAuthClientId
);
}
}
private handleBookingErrors(
err: Error | HttpError | unknown,
type?: "recurring" | `instant` | "no-show"
): void {
const errMsg =
type === "no-show"
? `Error while marking no-show.`
: `Error while creating ${type ? `${type} ` : ""}booking.`;
if (err instanceof HttpError) {
const httpError = err as HttpError;
throw new HttpException(httpError?.message ?? errMsg, httpError?.statusCode ?? 500);
}
if (err instanceof Error) {
const error = err as Error;
if (err instanceof HttpException) {
throw new HttpException(err.getResponse(), err.getStatus());
}
if (Object.values(ErrorCode).includes(error.message as unknown as ErrorCode)) {
throw new HttpException(error.message, 400);
}
throw new InternalServerErrorException(error?.message ?? errMsg);
}
throw new InternalServerErrorException(errMsg);
}
private transformToBoolean(v?: string): boolean {
return v && typeof v === "string" ? v.toLowerCase() === "true" : false;View on GitHub (pinned to 176037d0af)
Solutions
- Read the statusCode in the HTTP response — it reflects the original HttpError.statusCode and indicates the real problem (409 conflict, 402 payment, 400 bad request, etc.).
- Address the root cause indicated by the statusCode: resolve scheduling conflicts, retry payments, fix input validation errors.
- If the message is unhelpful, check server logs where the original HttpError was logged with its url, method, and data fields.
- Ensure your client handles the full range of status codes (400, 402, 409, 500) that the booking service can emit.
Defensive patterns
Strategy: try-catch
Try / catch
// Client-side: handle the propagated HttpError status codes
try {
await api.createBooking(payload);
} catch (err) {
switch (err.statusCode) {
case 409: handleConflict(); break;
case 402: handlePaymentFailure(); break;
case 400: handleValidationError(err.message); break;
default: handleGenericError(err);
}
} Prevention
- Handle the full range of HTTP status codes from booking endpoints — the statusCode reflects the original HttpError.
- Log err.message and err.statusCode together for diagnostics.
- For 409 conflicts, implement client-side availability checking before retrying.
- For 402 payment errors, ensure payment credentials are valid before booking.
When it happens
Trigger: Any booking creation, cancellation, no-show, or recurring booking flow where the underlying service (regularBookingService, recurringBookingService, handleCancelBooking, handleMarkNoShow) throws a HttpError — for example when an availability check fails, a payment provider returns an error, or a conferencing integration call fails upstream.
Common situations: The booking service throws HttpError with a specific status like 409 for booking conflicts, 402 for payment failures, or 400 for bad input. The message and statusCode from the HttpError are forwarded. Common during double-booking attempts, expired payment sessions, or when an app-store integration (e.g., Stripe, Zoom) returns an error.
Related errors
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/230e54ee8f9725ee.
Report an issue: GitHub.