calcom/cal.diy · warning · UnprocessableEntityException

${error?.message}

Error message

${error?.message}

What it means

A NestJS UnprocessableEntityException (HTTP 422) from SlotsService_2024_09_04.reserveSlot's round-robin branch. validateRoundRobinSlotAvailability threw an Error and its message is forwarded verbatim. NOTE: in this repository validateRoundRobinSlotAvailability is a stub (always returns true), so this error is effectively unreachable here; in the EE build it fires when no round-robin host is free for the slot.

Source

Thrown at apps/api/v2/src/modules/slots/slots-2024-09-04/services/slots.service.ts:163

            `Booking with id=${input.eventTypeId} at ${input.slotStart} has no more seats left.`
          );
        }
      }
    }

    const nonSeatedEventAlreadyBooked = !eventType.seatsPerTimeSlot && booking;
    const isRoundRobinEvent = eventType.schedulingType === SchedulingType.ROUND_ROBIN;

    if (nonSeatedEventAlreadyBooked && !isRoundRobinEvent) {
      throw new UnprocessableEntityException(`Can't reserve a slot if the event is already booked.`);
    }

    if (isRoundRobinEvent) {
      try {
        await validateRoundRobinSlotAvailability(input.eventTypeId, startDate, endDate, eventType.hosts);
      } catch (error) {
        if (error instanceof Error) {
          throw new UnprocessableEntityException(error?.message);
        }
        throw error;
      }
    } else {
      await this.checkSlotOverlap(input.eventTypeId, startDate.toISO(), endDate.toISO());
    }

    const reservationDuration = input.reservationDuration ?? DEFAULT_RESERVATION_DURATION;

    if (eventType.userId) {
      const slot = await this.slotsRepository.createSlot(
        eventType.userId,
        eventType.id,
        startDate.toISO(),
        endDate.toISO(),
        eventType.seatsPerTimeSlot !== null,
        reservationDuration
      );

View on GitHub (pinned to 176037d0af)

Solutions

  1. Re-query availability to find a slot where at least one round-robin host is free.
  2. Add more hosts to the round-robin event type.
  3. Widen the host pool (routedTeamMemberIds) if using routing.
  4. If you observe this in the OSS fork, treat it as unexpected and report it — the stub should not throw.

Example fix

// before
await reserve(rrEventTypeId, slotStart);

// after — pick a slot confirmed to have an available RR host
const slots = await calApi.slots.list({ eventTypeId: rrEventTypeId });
const open = slots.find(s => !s.away);
await reserve(rrEventTypeId, open.start);
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate availability before reserving a round-robin slot.
async function ensureRrSlotHasHost(eventTypeId: number, slotStart: string) {
  const slots = await cal.slots.list({ eventTypeId, start: slotStart, end: oneDayLater(slotStart) });
  const hit = Object.values(slots).flat().find(s => s.start === slotStart && !s.away);
  if (!hit) throw new UserFacingError('No round-robin host is free at that time.');
  return hit;
}
await ensureRrSlotHasHost(eventTypeId, slotStart);

Type guard

function isRoundRobinHostAvailable(slot: unknown): boolean {
  return typeof slot === 'object' && slot !== null && !(slot as any).away;
}

Try / catch

try {
  await cal.slots.reserve({ eventTypeId, slotStart });
} catch (e) {
  if (e instanceof HttpError && e.statusCode === 422) {
    // round-robbin: pick the next free slot
    const next = await nextFreeSlot(eventTypeId);
    return cal.slots.reserve({ eventTypeId, slotStart: next.start });
  }
  throw e;
}

Prevention

When it happens

Trigger: POST /v2/slots/reserve for a round-robin team event type where, in the EE validation, none of the hosts are available for the computed window. In this fork the stub never throws, so you will not see this in practice.

Common situations: Running against an EE build where host availability/busy times exclude everyone for that slot; hosts removed from the team after the slot list was generated.

Related errors


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