{"record":{"id":"4cba642ac14a0a72","repo":"calcom/cal.diy","slug":"google-meet-is-already-connected-for-this-team","errorCode":null,"errorMessage":"Google Meet is already connected for this team.","messagePattern":"Google Meet is already connected for this team\\.","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"warning","filePath":"apps/api/v2/src/modules/conferencing/services/google-meet.service.ts","lineNumber":36,"sourceCode":"    await this.validateGoogleCalendarConnection(userId, \"user\");\n\n    const googleMeetExists = await this.conferencingRepository.findGoogleMeet(userId);\n    if (googleMeetExists) {\n      throw new BadRequestException(\"Google Meet is already connected for this user.\");\n    }\n\n    return this.credentialsRepository.upsertUserAppCredential(GOOGLE_MEET_TYPE, {}, userId);\n  }\n\n  async connectGoogleMeetToTeam(teamId: number) {\n    await this.validateGoogleCalendarConnection(teamId, \"team\");\n\n    const googleMeetExists = await this.credentialsRepository.findCredentialByTypeAndTeamId(\n      GOOGLE_MEET_TYPE,\n      teamId\n    );\n    if (googleMeetExists) {\n      throw new BadRequestException(\"Google Meet is already connected for this team.\");\n    }\n\n    return this.credentialsRepository.upsertTeamAppCredential(GOOGLE_MEET_TYPE, {}, teamId);\n  }\n\n  /**\n   * Validate that Google Calendar is connected and valid for either a user or a team.\n   */\n  private async validateGoogleCalendarConnection(id: number, entity: \"user\" | \"team\") {\n    const googleCalendar =\n      entity === \"user\"\n        ? await this.credentialsRepository.findCredentialByTypeAndUserId(GOOGLE_CALENDAR_TYPE, id)\n        : await this.credentialsRepository.findCredentialByTypeAndTeamId(GOOGLE_CALENDAR_TYPE, id);\n\n    if (!googleCalendar) {\n      throw new BadRequestException(\"Google Meet requires a Google Calendar connection.\");\n    }\n","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/apps/api/v2/src/modules/conferencing/services/google-meet.service.ts#L18-L54","documentation":"Thrown by GoogleMeetService.connectGoogleMeetToTeam when a Google Meet conferencing app credential already exists for the given teamId. The service first validates a Google Calendar connection exists, then queries credentialsRepository.findCredentialByTypeAndTeamId for GOOGLE_MEET_TYPE and rejects duplicates via a NestJS BadRequestException (HTTP 400). This prevents a team from accumulating multiple Google Meet credentials.","triggerScenarios":"POST/PUT to the v2 conferencing connect endpoint for a team that already has a stored GOOGLE_MEET_TYPE credential. Happens on retry of a connection call, double-submit of a connect form, or an idempotency check before the upsert at the end of connectGoogleMeetToTeam.","commonSituations":"User clicks 'Connect Google Meet' twice; a frontend retry fires after a partial success; a previous team admin already connected it and a second admin tries again; a migration/seed left an orphan credential.","solutions":["Check the team's existing Google Meet credential before calling connect (GET the conferencing status endpoint) and skip if already present.","Disconnect (delete the existing GOOGLE_MEET_TYPE credential for the team) first, then reconnect.","Treat HTTP 400 with this message as success-equivalent in the client if the goal is just 'ensure connected'."],"exampleFix":"// before\nawait api.connectGoogleMeetToTeam(teamId);\n\n// after\nconst existing = await api.getTeamConferencing(teamId);\nif (!existing.googleMeet) {\n  await api.connectGoogleMeetToTeam(teamId);\n}","handlingStrategy":"validation","validationCode":"const existing = await credentialsRepository.findCredentialByTypeAndTeamId(GOOGLE_MEET_TYPE, teamId);\nif (existing) {\n  // already connected; skip or return the existing credential\n  return existing;\n}\nawait googleMeetService.connectGoogleMeetToTeam(teamId);","typeGuard":null,"tryCatchPattern":"try {\n  await googleMeetService.connectGoogleMeetToTeam(teamId);\n} catch (e) {\n  if (e instanceof BadRequestException && e.message.includes('already connected')) {\n    // idempotent success\n    return;\n  }\n  throw e;\n}","preventionTips":["Implement an idempotent 'ensure connected' helper that checks before calling connect.","Disable the connect button on the UI once a credential exists.","Document that duplicate connects are rejected so callers handle 400 gracefully."],"tags":["conferencing","google-meet","conflict","duplicate","nestjs"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}