calcom/cal.diy · error · NotFoundException

Event type with ID=${eventTypeId} does not exist.

Error message

Event type with ID=${eventTypeId} does not exist.

What it means

deleteEventType first calls getEventTypeById (by id only, not scoped to a user) and throws NotFoundException when that returns null. Ownership is checked separately afterward (see 424). So this specific throw fires only when the id does not exist at all.

Source

Thrown at apps/api/v2/src/platform/event-types/event-types_2024_06_14/services/event-types.service.ts:354

  async getUserToUpdateEvent(user: UserWithProfile) {
    const profileId = this.usersService.getUserMainProfile(user)?.id || null;
    const selectedCalendars = await this.selectedCalendarsRepository.getUserSelectedCalendars(user.id);
    const eventTypeSelectedCalendars =
      await this.selectedCalendarsRepository.getUserEventTypeSelectedCalendar(user.id);
    return {
      ...user,
      locale: user.locale ?? "en",
      profile: { id: profileId },
      userLevelSelectedCalendars: selectedCalendars,
      allSelectedCalendars: [...eventTypeSelectedCalendars, ...selectedCalendars],
    };
  }

  async deleteEventType(eventTypeId: number, userId: number) {
    const existingEventType = await this.eventTypesRepository.getEventTypeById(eventTypeId);
    if (!existingEventType) {
      throw new NotFoundException(`Event type with ID=${eventTypeId} does not exist.`);
    }

    this.checkUserOwnsEventType(userId, existingEventType);

    return this.eventTypesRepository.deleteEventType(eventTypeId);
  }

  checkUserOwnsEventType(userId: number, eventType: Pick<EventType, "id" | "userId">) {
    if (userId !== eventType.userId) {
      throw new ForbiddenException(`User with ID=${userId} does not own event type with ID=${eventType.id}`);
    }
  }

  async checkUserOwnsSchedule(userId: number, scheduleId: number | null | undefined) {
    if (!scheduleId) {
      return;
    }

View on GitHub (pinned to 176037d0af)

Solutions

  1. Treat a 404 on DELETE as a no-op success for idempotency.
  2. Confirm the id exists (and is owned) with a GET before deleting if you need a strict before-state.
  3. Refresh the event-type list to discard stale ids before deleting.

Example fix

// before
await api.deleteEventType(id); // throws 404 if already gone
// after
try { await api.deleteEventType(id); }
catch (e) { if (e.status === 404) return { deleted: false, reason: 'already-absent' }; throw e; }
Defensive patterns

Strategy: try-catch

Validate before calling

const et = await api.getEventTypeById(id);
if (!et) return { deleted: false, reason: 'absent' };

Type guard

null

Try / catch

try { await api.deleteEventType(id); return { deleted: true }; }
catch (e) {
  if (e.status === 404) return { deleted: false, reason: 'already-absent' };
  throw e;
}

Prevention

When it happens

Trigger: DELETE an event type id that was never created or was already deleted; double-delete from two clients; an id copied incorrectly.

Common situations: Idempotent delete flows where another client already removed the resource; retry of a delete after success; stale id from a cached list.

Related errors


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