calcom/cal.diy · warning · HttpError

Booking reference not found

Error message

Booking reference not found

What it means

Thrown by getBookingReference in the daily-webhook handler (HttpError) when no BookingReference is found for the roomName, or the reference has no bookingId. Notably the statusCode is 200 (not 404) — this is deliberate so the webhook responds success and Daily.co does not keep retrying for orphaned rooms. A log.error records the missing reference and roomName.

Source

Thrown at apps/web/lib/daily-webhook/getBookingReference.ts:20

import { HttpError } from "@calcom/lib/http-error";
import logger from "@calcom/lib/logger";
import { safeStringify } from "@calcom/lib/safeStringify";

const log = logger.getSubLogger({ prefix: ["daily-video-webhook-handler"] });

export const getBookingReference = async (roomName: string) => {
  const bookingReference = await BookingReferenceRepository.findDailyVideoReferenceByRoomName({ roomName });

  if (!bookingReference || !bookingReference.bookingId) {
    log.error(
      "bookingReference not found error:",
      safeStringify({
        bookingReference,
        roomName,
      })
    );

    throw new HttpError({ message: "Booking reference not found", statusCode: 200 });
  }

  return bookingReference;
};

View on GitHub (pinned to 176037d0af)

Solutions

  1. Wrap the webhook handler so a missing reference is logged/monitored but returns 2xx (the handler already does this via statusCode 200) — do not convert it to an error response.
  2. Alert on the rate of these 200-but-logged events to detect room/reference mismatches.
  3. Ensure booking references are only deleted after all expected webhooks have been processed, and that roomName generation stays stable.

Example fix

// before
const ref = await getBookingReference(roomName); // throws but returns 200

// after
let ref;
try {
  ref = await getBookingReference(roomName);
} catch (e) {
  // statusCode 200 is intentional — Daily will not retry
  metrics.increment('daily.orphan_room', { roomName });
  return Response.json({ ok: true, ignored: 'no reference' });
}
processReference(ref);
Defensive patterns

Strategy: try-catch

Validate before calling

// Resolve reference defensively in the webhook handler
let ref;
try {
  ref = await getBookingReference(roomName);
} catch (e) {
  metrics.increment('daily.orphan_room', { roomName });
  return Response.json({ ok: true, ignored: 'no reference' });
}
await processReference(ref);

Type guard

function isBookingReference(v: unknown): v is { bookingId: number } {
  return !!v && typeof v === 'object' &&
    typeof (v as any).bookingId === 'number';
}

Try / catch

try {
  const ref = await getBookingReference(roomName);
  await processReference(ref);
} catch (e) {
  // statusCode is 200 by design — Daily will not retry
  if (e instanceof HttpError && e.statusCode === 200) {
    metrics.increment('daily.missing_reference', { roomName });
    return Response.json({ ok: true, ignored: 'no reference' });
  }
  throw e;
}

Prevention

When it happens

Trigger: A Daily.co webhook arrives for a roomName with no corresponding booking reference: room created outside the booking flow, reference already deleted, test/synthetic webhook, room naming mismatch.

Common situations: Ad-hoc rooms created in Daily without a booking, webhook delivered for a cancelled booking whose reference was cleaned up, roomName format change breaking the lookup, environment room/test room.

Related errors


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