calcom/cal.diy · error · NotFoundException

Event type with id ${eventTypeId} not found

Error message

Event type with id ${eventTypeId} not found

What it means

After updateEventType writes through dbWrite.prisma, the service re-fetches the row via eventTypesRepository.getEventTypeById, which reads from dbRead (the read replica). If that read returns null it throws NotFoundException. The most common root cause is read-replica lag right after the write, but concurrent deletion or a wrong id also produce it.

Source

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

  ) {
    if (body.bookingFields) {
      this.checkHasUserAccessibleEmailBookingField(body.bookingFields);
    }
    await this.checkCanUpdateEventType(user.id, eventTypeId, body.scheduleId);
    const eventTypeUser = await this.getUserToUpdateEvent(user);

    await updateEventType({
      input: { id: eventTypeId, ...body },
      ctx: {
        user: eventTypeUser,
        prisma: this.dbWrite.prisma,
      },
    });

    const eventType = await this.eventTypesRepository.getEventTypeById(eventTypeId);

    if (!eventType) {
      throw new NotFoundException(`Event type with id ${eventTypeId} not found`);
    }

    return {
      ownerId: user.id,
      ...eventType,
    };
  }

  async checkCanUpdateEventType(userId: number, eventTypeId: number, scheduleId: number | undefined | null) {
    const existingEventType = await this.getUserEventType(userId, eventTypeId);
    if (!existingEventType) {
      throw new NotFoundException(`Event type with id ${eventTypeId} not found`);
    }
    this.checkUserOwnsEventType(userId, { id: eventTypeId, userId: existingEventType.ownerId });
    await this.checkUserOwnsSchedule(userId, scheduleId);
  }

  async getUserToUpdateEvent(user: UserWithProfile) {

View on GitHub (pinned to 176037d0af)

Solutions

  1. Retry the GET once after a short backoff to let the replica catch up.
  2. For the post-write read, read from the primary (dbWrite) instead of the read replica to get read-your-writes consistency.
  3. Guard against concurrent deletion by checking existence immediately before and after the update.
  4. Confirm the eventTypeId is owned by the caller before updating so the update is not a silent no-op.

Example fix

// before
await updateEventType({ input, ctx });
const et = await eventTypesRepository.getEventTypeById(id); // dbRead replica
// after
await updateEventType({ input, ctx });
const et = await dbWrite.prisma.eventType.findUnique({ where: { id } });
// or retry the replica fetch with backoff
Defensive patterns

Strategy: retry

Validate before calling

async function readAfterWrite(id, fetcher) {
  for (const delay of [0, 100, 300]) {
    const et = await fetcher(id);
    if (et) return et;
    await new Promise(r => setTimeout(r, delay));
  }
  return null;
}

Type guard

null

Try / catch

try {
  return await eventTypesRepository.getEventTypeById(id);
} catch (e) {
  if (e.name === 'NotFoundException') {
    // read replica may lag; retry from primary once
    return await dbWrite.prisma.eventType.findUnique({ where: { id } });
  }
  throw e;
}

Prevention

When it happens

Trigger: PATCH/PUT an event type where the write commits but the read replica has not yet propagated it; another process deletes the event type between the update and the re-fetch; the id supplied does not exist (update is a no-op) and the post-update fetch finds nothing.

Common situations: Production with primary/replica split and replication lag; high write throughput; a race where a second client deletes the event type mid-update; integration tests that point dbRead and dbWrite at different stores.

Related errors


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