calcom/cal.diy · error · BadRequestException
User already has an event type with this slug.
Error message
User already has an event type with this slug.
What it means
Thrown by EventTypesService_2024_06_14.checkCanCreateEventType (POST /v2/event-types, cal-api-version 2024-06-14) when getUserEventTypeBySlug returns a row — the user already owns an event type with the requested slug. Slug uniqueness is enforced per user before any write occurs. Identical message to the 2024_04_15 service; both versions share this contract.
Source
Thrown at apps/api/v2/src/platform/event-types/event-types_2024_06_14/services/event-types.service.ts:108
const hasAccess = await this.eventTypeAccessService.userIsEventTypeAdminOrOwner(
authUser,
eventType as unknown as EventType
);
if (!hasAccess) {
return null;
}
return {
ownerId: eventType.userId ?? 0,
...eventType,
};
}
async checkCanCreateEventType(userId: number, body: InputEventTransformed_2024_06_14) {
const existsWithSlug = await this.eventTypesRepository.getUserEventTypeBySlug(userId, body.slug);
if (existsWithSlug) {
throw new BadRequestException("User already has an event type with this slug.");
}
await this.checkUserOwnsSchedule(userId, body.scheduleId);
}
checkHasUserAccessibleEmailBookingField(bookingFields: (SystemField | CustomField)[]) {
const emailField = bookingFields.find((field) => field.type === "email" && field.name === "email");
const isEmailFieldRequiredAndVisible = emailField?.required && !emailField?.hidden;
if (!isEmailFieldRequiredAndVisible) {
throw new BadRequestException(
"checkIsEmailUserAccessible - Email booking field must be required and visible"
);
}
}
async getEventTypeByUsernameAndSlug(params: {
username: string;
eventTypeSlug: string;
orgSlug?: string;View on GitHub (pinned to 176037d0af)
Solutions
- GET /v2/event-types (cal-api-version 2024-06-14) and confirm the slug is unused before POSTing.
- Append a numeric suffix to the slug when the preferred one is taken.
- If retrying after a possible success, list event types and PATCH the existing one instead of re-creating.
- Derive slugs from a stable external id to make retries idempotent.
Example fix
// before
await api.post('/v2/event-types', { slug: 'intro-call', ... }, { headers: { 'cal-api-version': '2024-06-14' } });
// after
const mine = (await api.get('/v2/event-types', { headers: { 'cal-api-version': '2024-06-14' } })).data;
if (mine.some(e => e.slug === 'intro-call')) throw new Error('slug taken');
await api.post('/v2/event-types', { slug: 'intro-call', ... }, { headers: { 'cal-api-version': '2024-06-14' } }); Defensive patterns
Strategy: validation
Validate before calling
// Check slug uniqueness before create (2024_06_14)
const mine = (await api.get('/v2/event-types', { headers: { 'cal-api-version': '2024-06-14' } })).data ?? [];
if (mine.some((e) => e.slug === body.slug)) {
throw new Error(`slug ${body.slug} already used by this user`);
} Type guard
function isSlugAvailable(list: unknown, slug: string): boolean {
return Array.isArray(list) && !list.some((e) => typeof e === 'object' && e !== null && (e as any).slug === slug);
} Try / catch
try {
await api.post('/v2/event-types', body, { headers: { 'cal-api-version': '2024-06-14' } });
} catch (e) {
if (e.response?.status === 400 && e.response?.data?.message?.includes('slug')) {
// append suffix or switch to PATCH on the existing id
} else throw e;
} Prevention
- Derive slugs from a stable external id for idempotent retries.
- After a create timeout, list before retrying.
- Keep a client-side cache of used slugs per user.
When it happens
Trigger: POST /v2/event-types with a slug duplicating an existing one for the same user; retrying a successful create with the same slug; slug collision after a rename; importing event types without dedup.
Common situations: Network-retry of a succeeded create; deterministic slug generation from a title that already exists; migrating event types between users without changing the slug; frontend not refreshing after create.
Related errors
- User already has an event type with this slug.
- checkIsEmailUserAccessible - Email booking field must be req
- teamId is required for team events, please provide a valid t
- username is required for non-team events, please provide a v
- Event type with id ${eventTypeId} not found
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/e44e4e1457e5d93a.
Report an issue: GitHub.