calcom/cal.diy · error · BadRequestException
checkIsEmailUserAccessible - Email booking field must be req
Error message
checkIsEmailUserAccessible - Email booking field must be required and visible
What it means
Thrown by EventTypesService_2024_06_14.checkHasUserAccessibleEmailBookingField when the email booking field is not both `required` and not `hidden`. The 2024_06_14 create/update flow enforces that the `email` system field remains user-accessible (required and visible) so booking confirmations and attendee notifications can be delivered. It fires on both create (when bookingFields is provided) and update.
Source
Thrown at apps/api/v2/src/platform/event-types/event-types_2024_06_14/services/event-types.service.ts:117
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;
orgId?: number;
authUser?: AuthOptionalUser;
}) {
const user = await this.usersRepository.findByUsername(params.username, params.orgSlug, params.orgId);
if (!user) {
return null;
}
const eventType = await this.eventTypesRepository.getUserEventTypeBySlug(user.id, params.eventTypeSlug);View on GitHub (pinned to 176037d0af)
Solutions
- Ensure the bookingFields array includes an entry with type 'email', name 'email', required true, and hidden false (or omitted/undefined).
- When PATCHing only a subset of bookingFields, re-include the email field with required:true and hidden:false.
- Validate your payload against the SystemField schema before sending — use the platform-types definition.
- If you genuinely need a no-email event type, use a different flow (e.g. managed events) that does not route through this check.
Example fix
// before
await api.patch(`/v2/event-types/${id}`, {
bookingFields: [{ type: 'email', name: 'email', required: false, hidden: true }]
}, { headers: { 'cal-api-version': '2024-06-14' } });
// after
await api.patch(`/v2/event-types/${id}`, {
bookingFields: [{ type: 'email', name: 'email', required: true, hidden: false }]
}, { headers: { 'cal-api-version': '2024-06-14' } }); Defensive patterns
Strategy: type-guard
Validate before calling
// Ensure the email booking field is required and visible before create/update
function ensureEmailFieldAccessible(bookingFields: any[]) {
const email = bookingFields.find((f) => f.type === 'email' && f.name === 'email');
if (!email || !email.required || email.hidden) {
throw new Error('email booking field must be present, required, and not hidden');
}
} Type guard
function hasAccessibleEmailField(fields: unknown): boolean {
if (!Array.isArray(fields)) return false;
const email = fields.find(
(f) => typeof f === 'object' && f !== null && (f as any).type === 'email' && (f as any).name === 'email'
);
return !!email && (email as any).required === true && !(email as any).hidden;
} Try / catch
try {
await api.patch(`/v2/event-types/${id}`, { bookingFields }, { headers: { 'cal-api-version': '2024-06-14' } });
} catch (e) {
if (e.response?.status === 400 && e.response?.data?.message?.includes('Email booking field')) {
// re-include the email system field with required:true, hidden:false
} else throw e;
} Prevention
- Always include the email system field with required:true and hidden:false in bookingFields payloads.
- When PATCHing a subset of bookingFields, merge with the existing set rather than replacing blindly.
- Validate the payload with the platform-types SystemField schema in your test suite.
When it happens
Trigger: POST or PATCH /v2/event-types (cal-api-version 2024-06-14) with bookingFields where the email field is marked hidden:true, required:false, or is omitted entirely while other bookingFields are supplied; setting the email field to optional; removing the email field from the array.
Common situations: Customizing the booking form and accidentally toggling email off; importing an event type config from an older version where email was optional; a frontend builder that lets users hide the email field; partial updates that include bookingFields without the email entry.
Related errors
- User already has an event type with this slug.
- teamId is required for team events, please provide a valid t
- username is required for non-team events, please provide a v
- User already has an event type with this slug.
- Event type with id ${eventTypeId} not found
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/4bb0f68e48c5c007.
Report an issue: GitHub.