calcom/cal.diy · info · BadRequestException

Google Meet is already connected for this user.

Error message

Google Meet is already connected for this user.

What it means

Thrown by GoogleMeetService.connectGoogleMeetToUser when conferencingRepository.findGoogleMeet(userId) returns an existing credential — the user already has a google_meet credential row. Returns HTTP 400 via BadRequestException. Connecting again would create a duplicate; the existing credential is reused. Reached via POST /v2/conferencing/google_meet/connect → connectUserNonOauthApp.

Source

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

import { Injectable } from "@nestjs/common";

import { GOOGLE_CALENDAR_TYPE, GOOGLE_MEET_TYPE } from "@calcom/platform-constants";

@Injectable()
export class GoogleMeetService {
  private logger = new Logger("GoogleMeetService");

  constructor(
    private readonly conferencingRepository: ConferencingRepository,
    private readonly credentialsRepository: CredentialsRepository
  ) {}

  async connectGoogleMeetToUser(userId: number) {
    await this.validateGoogleCalendarConnection(userId, "user");

    const googleMeetExists = await this.conferencingRepository.findGoogleMeet(userId);
    if (googleMeetExists) {
      throw new BadRequestException("Google Meet is already connected for this user.");
    }

    return this.credentialsRepository.upsertUserAppCredential(GOOGLE_MEET_TYPE, {}, userId);
  }

  async connectGoogleMeetToTeam(teamId: number) {
    await this.validateGoogleCalendarConnection(teamId, "team");

    const googleMeetExists = await this.credentialsRepository.findCredentialByTypeAndTeamId(
      GOOGLE_MEET_TYPE,
      teamId
    );
    if (googleMeetExists) {
      throw new BadRequestException("Google Meet is already connected for this team.");
    }

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

View on GitHub (pinned to 176037d0af)

Solutions

  1. Before calling connect, check GET /v2/conferencing — if google_meet is listed, skip the connect call.
  2. Disable the connect button immediately on click (debounce) to prevent double-submit.
  3. Treat this 400 as success-equivalent in the client (idempotent connect) since the end state — Google Meet connected — is achieved.
  4. If you want true idempotency, switch the service to upsert instead of throw on duplicate.

Example fix

// before
await api.connectConferencing('google_meet');

// after
const installed = await api.listConferencingApps();
if (!installed.data.some(a => a.slug === 'google_meet')) {
  await api.connectConferencing('google_meet');
} else {
  showToast('Google Meet is already connected.');
}
Defensive patterns

Strategy: validation

Validate before calling

async function googleMeetAlreadyConnected(conferencingRepository: ConferencingRepository, userId: number): Promise<boolean> {
  return Boolean(await conferencingRepository.findGoogleMeet(userId));
}

if (await googleMeetAlreadyConnected(conferencingRepository, userId)) {
  return { status: 'already_connected', app: 'google_meet' };
}

Type guard

function isGoogleMeetCredential<T extends { type: string }>(c: T | null): c is T & { type: 'google_meet' } {
  return c !== null && c.type === 'google_meet';
}

Try / catch

try {
  await googleMeetService.connectGoogleMeetToUser(userId);
} catch (e) {
  if (e instanceof BadRequestException && /already connected/i.test(e.message)) {
    // idempotent — treat as success
    return { status: 'already_connected' };
  }
  throw e;
}

Prevention

When it happens

Trigger: User clicks 'Connect Google Meet' a second time; the frontend did not refresh its connected-apps state after the first connect; a retry fired because the first response was slow.

Common situations: UI button stays enabled after connect; double-submit (no debounce); race between two connect clicks; the connect succeeded but the response was lost and the client retried.

Related errors


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