calcom/cal.diy · error · NotFoundException
Booking with uid ${uid} not found
Error message
Booking with uid ${uid} not found What it means
Thrown by EventTypesAtomService.getUserPaymentInfo when the payment record exists (rawPayment is truthy) but its booking relation is null. This means the payment row has a null or missing foreign key to the booking table, indicating a data integrity issue. The payment was found but is orphaned — no booking is associated with it, so the start/end times and event type cannot be resolved.
Source
Thrown at apps/api/v2/src/modules/atoms/services/event-types-atom.service.ts:321
isInstalled: !!userCredentialIds.length || !!teams.length || app.isGlobal,
isSetupAlready,
...(app.dependencies && { dependencyData }),
};
}
)
);
return apps[0];
}
async getUserPaymentInfo(uid: string) {
const rawPayment = await this.atomsRepository.getRawPayment(uid);
if (!rawPayment) throw new NotFoundException(`Payment with uid ${uid} not found`);
const { data, booking: _booking, ...restPayment } = rawPayment;
const payment = {
...restPayment,
data: data as Record<string, unknown>,
};
if (!_booking) throw new NotFoundException(`Booking with uid ${uid} not found`);
const { startTime, endTime, eventType, ...restBooking } = _booking;
const booking = {
...restBooking,
startTime: startTime.toString(),
endTime: endTime.toString(),
};
if (!eventType) throw new NotFoundException(`Event type with uid ${uid} not found`);
if (eventType.users.length === 0 && !eventType.team)
throw new NotFoundException(`No users found or no team present for event type with uid ${uid}`);
const [user] = eventType?.users.length
? eventType.users
: [{ name: null, theme: null, hideBranding: null, username: null }];
const profile = {
name: eventType.team?.name || user?.name || null,
theme: (!eventType.team?.name && user?.theme) || null,
hideBranding: eventType.team?.hideBranding || user?.hideBranding || null,
};
return {View on GitHub (pinned to 176037d0af)
Solutions
- Investigate the payment record in the database: check if bookingId is null or references a non-existent booking.
- If this is a timing issue (webhook race), retry after a short delay to see if the booking becomes available.
- Run a data integrity check: SELECT p.uid, p.bookingId, b.id FROM payment p LEFT JOIN booking b ON p.bookingId = b.id WHERE b.id IS NULL.
- If the booking was legitimately deleted, remove the orphaned payment record or re-associate it.
Example fix
// before: no retry on transient missing booking
const info = await api.get(`/v2/atoms/payment-info/${paymentUid}`);
// after: retry with backoff for webhook race conditions
const fetchWithRetry = async (uid, retries = 3) => {
for (let i = 0; i < retries; i++) {
try {
return await api.get(`/v2/atoms/payment-info/${uid}`);
} catch (e) {
if (e.statusCode === 404 && i < retries - 1) {
await new Promise(r => setTimeout(r, 1000 * (i + 1)));
continue;
}
throw e;
}
}
}; Defensive patterns
Strategy: retry
Validate before calling
// For webhook-driven flows, verify the booking exists before querying payment info
const verifyBookingExists = async (api: ApiClient, paymentUid: string): Promise<void> => {
const payment = await api.get(`/v2/payments/${paymentUid}`);
if (!payment?.bookingId) {
throw new Error('Payment exists but has no associated booking. Possible data integrity issue.');
}
}; Try / catch
// Retry for webhook race conditions where booking hasn't committed yet
const getPaymentInfoWithRetry = async (uid: string, maxRetries = 3): Promise<any> => {
for (let i = 0; i < maxRetries; i++) {
try {
return await api.get(`/v2/atoms/payment-info/${uid}`);
} catch (err: any) {
const msg = err?.response?.data?.message ?? '';
if (err?.response?.status === 404 && msg.includes('Booking') && i < maxRetries - 1) {
await new Promise(r => setTimeout(r, 1000 * (i + 1)));
continue;
}
throw err;
}
}
}; Prevention
- In webhook handlers, delay payment-info queries until after the booking transaction commits.
- Run periodic data integrity checks: SELECT p.uid FROM payment p LEFT JOIN booking b ON p."bookingId" = b.id WHERE p."bookingId" IS NOT NULL AND b.id IS NULL.
- When processing Stripe webballs, use idempotency keys to prevent duplicate payment records with missing bookings.
When it happens
Trigger: A payment record exists in the database with a null bookingId or a bookingId referencing a deleted booking. The payment was created by a webhook before the booking was committed (race condition). A data migration or manual database edit broke the foreign key relationship. The booking was hard-deleted but the payment was not cascaded.
Common situations: Stripe webhook arrives before the booking transaction commits (timing issue). Manual database cleanup that deleted bookings without cleaning payments. A failed booking flow that partially created a payment record. Database replication lag where the booking hasn't propagated to the read replica.
Related errors
- Event type with uid ${uid} not found
- Payment with uid ${uid} not found
- No users found or no team present for event type with uid ${
- Team with id ${teamId} not found
- Event type with id ${eventTypeId} not found
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/511ff19fa754d2c9.
Report an issue: GitHub.