Bug Description
The idempotency key unique constraint is only applied when a booking is created directly as ACCEPTED. When a booking transitions from PENDING to ACCEPTED via the confirm handler, the key is never set. Because PostgreSQL allows multiple NULL values in a unique column, two overlapping PENDING bookings can both transition to ACCEPTED without triggering the constraint.
Affected file
packages/prisma/extensions/booking-idempotency-key.ts (lines 28–35) — key is set only in the create path with ACCEPTED status, not in the update path:
if (result.status === BookingStatus.ACCEPTED) {
// only runs on initial create with ACCEPTED status
await client.booking.update({ where: { id: result.id }, data: { idempotencyKey: ... } })
}
Fix
Extend the idempotency-key extension to also fire on update operations that change status to BookingStatus.ACCEPTED (i.e. the PENDING → ACCEPTED transition path in confirm.handler.ts).
Related
Environment
cal.com main branch (2026-08-13).
Bug Description
The idempotency key unique constraint is only applied when a booking is created directly as
ACCEPTED. When a booking transitions fromPENDINGtoACCEPTEDvia the confirm handler, the key is never set. Because PostgreSQL allows multipleNULLvalues in a unique column, two overlappingPENDINGbookings can both transition toACCEPTEDwithout triggering the constraint.Affected file
packages/prisma/extensions/booking-idempotency-key.ts(lines 28–35) — key is set only in thecreatepath withACCEPTEDstatus, not in theupdatepath:Fix
Extend the idempotency-key extension to also fire on
updateoperations that changestatustoBookingStatus.ACCEPTED(i.e. thePENDING → ACCEPTEDtransition path inconfirm.handler.ts).Related
Environment
cal.com main branch (2026-08-13).