calcom/cal.diy · error · BadRequestException
Failed to create calendar event
Error message
Failed to create calendar event
What it means
Thrown by createEventWithClient when calendar.events.insert resolves but response.data is falsy — Google accepted the request but returned an empty body. This is a defensive guard before the success-path cast; the surrounding catch maps any thrown Google API error to the same message via mapGoogleApiError. Returns HTTP 400.
Source
Thrown at apps/api/v2/src/modules/cal-unified-calendars/services/google-calendar.service.ts:269
timeZone: body.start.timeZone,
},
end: {
dateTime: body.end.time,
timeZone: body.end.timeZone,
},
attendees: body.attendees?.map((a) => ({
email: a.email,
displayName: a.name,
})),
};
try {
const response = await calendar.events.insert({
calendarId: effectiveCalendarId,
requestBody,
sendUpdates: "none",
});
if (!response.data) {
throw new BadRequestException("Failed to create calendar event");
}
return response.data as GoogleCalendarEventResponse;
} catch (error) {
if (error instanceof HttpException) throw error;
throw this.mapGoogleApiError(error, "Failed to create calendar event");
}
}
private async getEventWithClient(
calendar: calendar_v3.Calendar,
calendarId: string,
eventId: string
): Promise<GoogleCalendarEventResponse> {
const effectiveCalendarId = calendarId || "primary";
try {
const event = await calendar.events.get({
calendarId: effectiveCalendarId,
eventId,View on GitHub (pinned to 176037d0af)
Solutions
- Inspect the full error in server logs — if it came from mapGoogleApiError, the underlying GaxiosError has the Google reason; capture error.response.data.error.errors for the precise cause.
- Validate the calendarId belongs to the authenticated user and is writable.
- Retry once for transient empty-body responses; if it persists, file a Google API issue with the request id.
- Sanitize the event payload (title length, attendee email format, timezone IANA names) before insert.
Example fix
// before
const response = await calendar.events.insert({ calendarId, requestBody });
if (!response.data) {
throw new BadRequestException('Failed to create calendar event');
}
// after: log the underlying detail for diagnostics
if (!response.data) {
this.logger.error('Google insert returned empty body', { calendarId, status: response.status });
throw new InternalServerErrorException('Google Calendar returned an unexpected empty response');
} Defensive patterns
Strategy: try-catch
Validate before calling
function validateCreateEventInput(body: CreateUnifiedCalendarEventInput): string[] {
const errors: string[] = [];
if (!body.title || body.title.length > 1024) errors.push('title required, max 1024 chars');
if (!body.start?.time || !body.end?.time) errors.push('start.time and end.time required');
if (body.attendees) {
for (const a of body.attendees) {
if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(a.email)) errors.push(`invalid attendee email: ${a.email}`);
}
}
return errors;
}
const errs = validateCreateEventInput(body);
if (errs.length) throw new BadRequestException(errs.join('; ')); Type guard
function isGoogleInsertSuccess(r: { data?: unknown }): r is { data: Record<string, unknown> } {
return Boolean(r && typeof r.data === 'object' && r.data !== null && 'id' in (r.data as object));
} Try / catch
try {
return await googleCalendarService.createEventForUser(userId, calId, body);
} catch (e) {
if (e instanceof BadRequestException && /Failed to create/.test(e.message)) {
// surface generic failure; log correlation id for ops
logger.error('create event failed', { userId, calId, body });
throw new ApiError('event_create_failed', 502);
}
throw e;
} Prevention
- Validate the event payload (title length, attendee emails, IANA timezone) before the API call.
- Confirm the calendarId is owned and writable by the authenticated user.
- Log the underlying GaxiosError reason so 400s are diagnosable, not opaque.
- For transient empty-body responses, retry once with backoff.
When it happens
Trigger: Google Calendar API returns 2xx with an empty body (rare — usually a partial outage or intermediate proxy stripping the body), or a malformed calendarId that the API silently no-ops on. More commonly this exact message surfaces when the insert call itself throws and mapGoogleApiError maps a 400 to BadRequestException with the fallback string.
Common situations: calendarId references a calendar the user can write metadata about but not insert into; transient Google API quirk; an API gateway or proxy between the service and Google that rewrites responses; time-zone or attendee payload that triggers a soft 400.
Related errors
- Event not found
- Failed to update event
- No valid credentials available for Google Calendar
- Google Calendar is not connected for this user
- Google Calendar credentials are invalid. Please reconnect.
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/5fb759ac15ad851d.
Report an issue: GitHub.