{"record":{"id":"5fb759ac15ad851d","repo":"calcom/cal.diy","slug":"failed-to-create-calendar-event","errorCode":null,"errorMessage":"Failed to create calendar event","messagePattern":"Failed to create calendar event","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"apps/api/v2/src/modules/cal-unified-calendars/services/google-calendar.service.ts","lineNumber":269,"sourceCode":"        timeZone: body.start.timeZone,\n      },\n      end: {\n        dateTime: body.end.time,\n        timeZone: body.end.timeZone,\n      },\n      attendees: body.attendees?.map((a) => ({\n        email: a.email,\n        displayName: a.name,\n      })),\n    };\n    try {\n      const response = await calendar.events.insert({\n        calendarId: effectiveCalendarId,\n        requestBody,\n        sendUpdates: \"none\",\n      });\n      if (!response.data) {\n        throw new BadRequestException(\"Failed to create calendar event\");\n      }\n      return response.data as GoogleCalendarEventResponse;\n    } catch (error) {\n      if (error instanceof HttpException) throw error;\n      throw this.mapGoogleApiError(error, \"Failed to create calendar event\");\n    }\n  }\n\n  private async getEventWithClient(\n    calendar: calendar_v3.Calendar,\n    calendarId: string,\n    eventId: string\n  ): Promise<GoogleCalendarEventResponse> {\n    const effectiveCalendarId = calendarId || \"primary\";\n    try {\n      const event = await calendar.events.get({\n        calendarId: effectiveCalendarId,\n        eventId,","sourceCodeStart":251,"sourceCodeEnd":287,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/apps/api/v2/src/modules/cal-unified-calendars/services/google-calendar.service.ts#L251-L287","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst response = await calendar.events.insert({ calendarId, requestBody });\nif (!response.data) {\n  throw new BadRequestException('Failed to create calendar event');\n}\n\n// after: log the underlying detail for diagnostics\nif (!response.data) {\n  this.logger.error('Google insert returned empty body', { calendarId, status: response.status });\n  throw new InternalServerErrorException('Google Calendar returned an unexpected empty response');\n}","handlingStrategy":"try-catch","validationCode":"function validateCreateEventInput(body: CreateUnifiedCalendarEventInput): string[] {\n  const errors: string[] = [];\n  if (!body.title || body.title.length > 1024) errors.push('title required, max 1024 chars');\n  if (!body.start?.time || !body.end?.time) errors.push('start.time and end.time required');\n  if (body.attendees) {\n    for (const a of body.attendees) {\n      if (!/^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$/.test(a.email)) errors.push(`invalid attendee email: ${a.email}`);\n    }\n  }\n  return errors;\n}\n\nconst errs = validateCreateEventInput(body);\nif (errs.length) throw new BadRequestException(errs.join('; '));","typeGuard":"function isGoogleInsertSuccess(r: { data?: unknown }): r is { data: Record<string, unknown> } {\n  return Boolean(r && typeof r.data === 'object' && r.data !== null && 'id' in (r.data as object));\n}","tryCatchPattern":"try {\n  return await googleCalendarService.createEventForUser(userId, calId, body);\n} catch (e) {\n  if (e instanceof BadRequestException && /Failed to create/.test(e.message)) {\n    // surface generic failure; log correlation id for ops\n    logger.error('create event failed', { userId, calId, body });\n    throw new ApiError('event_create_failed', 502);\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["google-calendar","google-api","event-create","nestjs","diagnostics"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}