calcom/cal.diy · warning · BadRequestException

${action} is currently only available for Google Calendar. O

Error message

${action} is currently only available for Google Calendar. Office 365 and Apple support is coming soon.

What it means

Thrown by UnifiedCalendarService.ensureGoogleCalendar when the calendar type slug passed to a unified-calendar endpoint is not exactly the GOOGLE_CALENDAR constant. The message interpolates the action name (e.g. 'Meeting details', 'Create event', 'List events') so the caller knows which operation was blocked. Returns HTTP 400. This is the strategy gate that limits the unified API to Google until Office 365/Apple are implemented.

Source

Thrown at apps/api/v2/src/modules/cal-unified-calendars/services/unified-calendar.service.ts:55

  [OFFICE_365_CALENDAR_TYPE]: OFFICE_365_CALENDAR,
  [APPLE_CALENDAR_TYPE]: APPLE_CALENDAR,
};

@Injectable()
export class UnifiedCalendarService {
  private readonly pipe = new GoogleCalendarEventOutputPipe();

  constructor(
    private readonly googleCalendarService: GoogleCalendarService,
    private readonly freebusyService: UnifiedCalendarsFreebusyService,
    private readonly calendarsService: CalendarsService
  ) {}

  // ─── Strategy: validate calendar type ──────────────────────────────────

  private ensureGoogleCalendar(calendar: string, action: string): void {
    if (calendar !== GOOGLE_CALENDAR) {
      throw new BadRequestException(
        `${action} is currently only available for Google Calendar. Office 365 and Apple support is coming soon.`
      );
    }
  }

  private transformEvent(event: GoogleCalendarEventResponse) {
    return this.pipe.transform(event);
  }

  private transformEvents(events: GoogleCalendarEventResponse[]) {
    return events.map((e) => this.pipe.transform(e));
  }

  // ─── Connections ───────────────────────────────────────────────────────

  async getConnections(
    userId: number
  ): Promise<Array<{ connectionId: string; type: "google" | "office365" | "apple"; email: string | null }>> {

View on GitHub (pinned to 176037d0af)

Solutions

  1. Gate UI affordances on calendar type: only show event-create/edit/list for google_calendar connections.
  2. Verify the calendar slug matches the exact value of GOOGLE_CALENDAR from @calcom/platform-constants (import the constant, do not hardcode).
  3. For non-Google calendars, return a friendly 'unsupported provider' state from your integration layer rather than calling the API.
  4. Track provider support rollout and update the gate once Office 365/Apple endpoints land.

Example fix

// before
import { GOOGLE_CALENDAR, OFFICE_365_CALENDAR } from '@calcom/platform-constants';
await api.listEvents(OFFICE_365_CALENDAR, userId, calId, t0, t1);

// after
import { GOOGLE_CALENDAR } from '@calcom/platform-constants';
if (calendar !== GOOGLE_CALENDAR) {
  return { status: 'unsupported_provider', provider: calendar };
}
await api.listEvents(GOOGLE_CALENDAR, userId, calId, t0, t1);
Defensive patterns

Strategy: type-guard

Validate before calling

import { GOOGLE_CALENDAR } from '@calcom/platform-constants';

function ensureGoogleCalendar(calendar: string, action: string): void {
  if (calendar !== GOOGLE_CALENDAR) {
    throw new Error(`${action} unsupported for ${calendar}; supported: ${GOOGLE_CALENDAR}`);
  }
}

ensureGoogleCalendar(req.body.calendar, 'Create event');

Type guard

import { GOOGLE_CALENDAR } from '@calcom/platform-constants';

function isSupportedCalendar(calendar: string): calendar is typeof GOOGLE_CALENDAR {
  return calendar === GOOGLE_CALENDAR;
}

Try / catch

try {
  await unifiedCalendarService.listEvents(calendar, userId, calId, t0, t1);
} catch (e) {
  if (e instanceof BadRequestException && /only available for Google Calendar/.test(e.message)) {
    return res.status(400).json({ code: 'unsupported_provider', supported: ['google_calendar'] });
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling any user-scoped unified-calendar endpoint with calendar=office_365_calendar or calendar=apple_calendar — getEventDetails, updateEventDetails, listEvents, createEvent, deleteEvent, getFreeBusy all invoke ensureGoogleCalendar first.

Common situations: Frontend uses the same UI for all calendar types but only Google is wired; an integration selects the user's default calendar type without checking it's Google; typo in the calendar slug (e.g. 'google' instead of the constant value).

Related errors


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