calcom/cal.diy · error · BadRequestException

Google Meet requires a Google Calendar connection.

Error message

Google Meet requires a Google Calendar connection.

What it means

Thrown inside validateGoogleCalendarConnection when no Google Calendar credential is found for the user or team. Google Meet is implemented as a dependent app: it requires a valid Google Calendar credential to exist first. The check runs findCredentialByTypeAndUserId or findCredentialByTypeAndTeamId for GOOGLE_CALENDAR_TYPE; a falsy result raises a BadRequestException (HTTP 400).

Source

Thrown at apps/api/v2/src/modules/conferencing/services/google-meet.service.ts:52

    );
    if (googleMeetExists) {
      throw new BadRequestException("Google Meet is already connected for this team.");
    }

    return this.credentialsRepository.upsertTeamAppCredential(GOOGLE_MEET_TYPE, {}, teamId);
  }

  /**
   * Validate that Google Calendar is connected and valid for either a user or a team.
   */
  private async validateGoogleCalendarConnection(id: number, entity: "user" | "team") {
    const googleCalendar =
      entity === "user"
        ? await this.credentialsRepository.findCredentialByTypeAndUserId(GOOGLE_CALENDAR_TYPE, id)
        : await this.credentialsRepository.findCredentialByTypeAndTeamId(GOOGLE_CALENDAR_TYPE, id);

    if (!googleCalendar) {
      throw new BadRequestException("Google Meet requires a Google Calendar connection.");
    }

    if (googleCalendar.invalid) {
      throw new BadRequestException(
        "Google Meet requires a valid Google Calendar connection. Please reconnect Google Calendar."
      );
    }
  }
}

View on GitHub (pinned to 176037d0af)

Solutions

  1. Connect Google Calendar first for the same user or team, then retry the Google Meet connect.
  2. Verify the correct userId/teamId is being passed (mismatched scope is the most common cause).
  3. If Google Calendar was connected but revoked, re-run the Google Calendar OAuth flow to recreate the credential.

Example fix

// before
await googleMeetService.connectGoogleMeetToUser(userId);

// after
const hasGcal = await credentialsRepository.findCredentialByTypeAndUserId(GOOGLE_CALENDAR_TYPE, userId);
if (!hasGcal) {
  await googleCalendarService.connect(userId);
}
await googleMeetService.connectGoogleMeetToUser(userId);
Defensive patterns

Strategy: validation

Validate before calling

const hasGcal = entity === 'team'
  ? await credentialsRepository.findCredentialByTypeAndTeamId(GOOGLE_CALENDAR_TYPE, id)
  : await credentialsRepository.findCredentialByTypeAndUserId(GOOGLE_CALENDAR_TYPE, id);
if (!hasGcal) {
  throw new Error('Connect Google Calendar before Google Meet.');
}
await googleMeetService.connect(entity, id);

Try / catch

try {
  await googleMeetService.connectGoogleMeetToUser(userId);
} catch (e) {
  if (e instanceof BadRequestException && /requires a Google Calendar connection/.test(e.message)) {
    await googleCalendarService.connect(userId);
    return googleMeetService.connectGoogleMeetToUser(userId);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling connectGoogleMeetToUser or connectGoogleMeetToTeam for an entity that has never connected Google Calendar, or whose Google Calendar credential was deleted. The guard fires before any Google Meet credential is written.

Common situations: Onboarding a team that skips the Google Calendar step; a user connects Outlook/Office365 calendar then tries Google Meet; Google Calendar credential revoked from the Google side and pruned; wrong teamId/userId passed.

Related errors


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