calcom/cal.diy · error · NotFoundException

Event Type not found

Error message

Event Type not found

What it means

NotFoundException (HTTP 404) thrown by SlotsInputService_2024_09_04.transformGetSlotsQuery() when getEventType(query) returns null. This is the input-transformation gate for the 2024-09-04 slots endpoint: every other field (duration, usernames, timeZone, rescheduleUid) is derived from the resolved event type, so a missing event type aborts before any slot computation.

Source

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

export type InternalGetSlotsQueryWithRouting = InternalGetSlotsQuery & {
  routedTeamMemberIds: number[] | null;
  skipContactOwner: boolean;
  teamMemberEmail: string | null;
};

@Injectable()
export class SlotsInputService_2024_09_04 {
  constructor(
    private readonly eventTypeRepository: EventTypesRepository_2024_06_14,
    private readonly usersRepository: UsersRepository,
    private readonly teamsRepository: TeamsRepository,
    private readonly teamsEventTypesRepository: TeamsEventTypesRepository
  ) {}

  async transformGetSlotsQuery(query: GetSlotsInput_2024_09_04): Promise<InternalGetSlotsQuery> {
    const eventType = await this.getEventType(query);
    if (!eventType) {
      throw new NotFoundException(`Event Type not found`);
    }
    const isTeamEvent = !!eventType?.teamId;

    const startTime = this.adjustStartTime(query.start);
    const endTime = this.adjustEndTime(query.end);
    const duration = query.duration;
    const eventTypeId = eventType.id;
    const eventTypeSlug = eventType.slug;
    const usernameList = "usernames" in query ? query.usernames : [];
    const timeZone = query.timeZone;
    const orgSlug = "organizationSlug" in query ? query.organizationSlug : null;
    const rescheduleUid = query.bookingUidToReschedule || null;

    return {
      isTeamEvent,
      startTime,
      endTime,
      duration,

View on GitHub (pinned to 176037d0af)

Solutions

  1. Verify the event type slug/id exists (and is in the right org context) before requesting slots.
  2. For slug-based flows, handle 404 by showing 'event no longer available' and refreshing the list.
  3. If rescheduling, confirm the original booking's event type still exists before calling the slots endpoint.

Example fix

// before
api.get('/slots/2024-09-04', { eventTypeSlug: 'old-slug', startTime, endTime });
// after — validate slug first
const et = await api.getEventTypeBySlug('old-slug');
if (!et) { showNotFound(); return; }
api.get('/slots/2024-09-04', { eventTypeId: et.id, startTime, endTime });
Defensive patterns

Strategy: try-catch

Validate before calling

async function resolveEventType(slugOrId: string | number) {
  const et = typeof slugOrId === 'number'
    ? await api.getEventType(slugOrId).catch(() => null)
    : await api.getEventTypeBySlug(slugOrId).catch(() => null);
  if (!et) throw new Error(`Event type ${slugOrId} not found`);
  return et;
}

Type guard

const eventTypeResolves = async (slugOrId: string | number): Promise<boolean> =>
  Boolean(await resolveEventType(slugOrId).catch(() => null));

Try / catch

try { await api.getSlots({ eventTypeSlug }); }
catch (e) { if (e.status === 404) { showEventUnavailable(); } else throw e; }

Prevention

When it happens

Trigger: GET /v2/slots/2024-09-04 with an eventTypeId or event-type slug that does not resolve (deleted, never existed, belongs to another org, or slug typo); reschedule via bookingUidToReschedule whose event type no longer exists.

Common situations: Slug-based deep links to a renamed/deleted event type; org subdomain routing resolving the wrong org so the event type isn't found; cache of a slug after the event type was edited; team event type removed between link generation and click.

Related errors


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