{"record":{"id":"d2497649946f8f1f","repo":"calcom/cal.diy","slug":"invalid-conferencing-app-available-apps-google-m","errorCode":null,"errorMessage":"Invalid conferencing app. Available apps: GOOGLE_MEET.","messagePattern":"Invalid conferencing app\\. Available apps: GOOGLE_MEET\\.","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"warning","filePath":"apps/api/v2/src/modules/conferencing/services/conferencing.service.ts","lineNumber":51,"sourceCode":"    private readonly conferencingRepository: ConferencingRepository,\n    private readonly usersRepository: UsersRepository,\n    private readonly tokensRepository: TokensRepository,\n    private readonly googleMeetService: GoogleMeetService,\n    private readonly zoomVideoService: ZoomVideoService,\n    private readonly office365VideoService: Office365VideoService\n  ) {}\n\n  async getConferencingApps(userId: number) {\n    return this.conferencingRepository.findConferencingApps(userId);\n  }\n\n  async connectUserNonOauthApp(app: string, userId: number) {\n    switch (app) {\n      case GOOGLE_MEET:\n        const credential = await this.googleMeetService.connectGoogleMeetToUser(userId);\n        return credential;\n      default:\n        throw new BadRequestException(\"Invalid conferencing app. Available apps: GOOGLE_MEET.\");\n    }\n  }\n\n  async connectOauthApps(\n    app: string,\n    code: string,\n    decodedCallbackState: OAuthCallbackState,\n    teamId?: number\n  ) {\n    const userId = await this.tokensRepository.getAccessTokenOwnerId(decodedCallbackState.accessToken);\n    if (!userId) {\n      throw new UnauthorizedException(\"Invalid Access token.\");\n    }\n    switch (app) {\n      case ZOOM:\n        return await this.zoomVideoService.connectZoomApp(decodedCallbackState, code, userId, teamId);\n\n      case OFFICE_365_VIDEO:","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/apps/api/v2/src/modules/conferencing/services/conferencing.service.ts#L33-L69","documentation":"Thrown by ConferencingService.connectUserNonOauthApp when the app slug is not GOOGLE_MEET. This branch handles apps that do not require OAuth (only Google Meet, which derives from the user's existing Google Calendar connection). Returns HTTP 400. The endpoint POST /v2/conferencing/{app}/connect only documents GOOGLE_MEET as a valid value.","triggerScenarios":"Calling POST /v2/conferencing/{app}/connect with app=zoom or app=office365_video — those require the OAuth flow (auth-url → callback), not the direct connect endpoint. Also any unknown slug like 'teams'.","commonSituations":"Client routes all conferencing connects through the same endpoint regardless of OAuth requirement; hardcoded slug list out of sync with the constants; integration assumes all apps connect directly.","solutions":["For GOOGLE_MEET only, call POST /v2/conferencing/google_meet/connect.","For ZOOM and OFFICE_365_VIDEO, use the OAuth flow: GET /v2/conferencing/{app}/oauth/auth-url, redirect, then handle the callback.","Validate the app slug client-side against the documented set for the connect endpoint before issuing the request.","Update the API client to expose separate connect/connectOauth methods keyed on the app's OAuth requirement."],"exampleFix":"// before\nawait api.connectConferencing('zoom'); // wrong endpoint\n\n// after\nconst OAUTH_APPS = ['zoom', 'office365_video'];\nif (OAUTH_APPS.includes(app)) {\n  const { data } = await api.getOauthUrl(app);\n  window.location.href = data.authUrl;\n} else {\n  await api.connectConferencing(app); // google_meet\n}","handlingStrategy":"validation","validationCode":"import { GOOGLE_MEET } from '@calcom/platform-constants';\n\nfunction validateNonOauthApp(app: string): void {\n  if (app !== GOOGLE_MEET) {\n    throw new Error(`${app} cannot be connected directly. Use the OAuth flow for ${app}.`);\n  }\n}\n\nvalidateNonOauthApp(req.params.app);","typeGuard":"import { GOOGLE_MEET } from '@calcom/platform-constants';\n\nfunction isDirectConnectApp(app: string): app is typeof GOOGLE_MEET {\n  return app === GOOGLE_MEET;\n}","tryCatchPattern":"try {\n  await conferencingService.connectUserNonOauthApp(app, userId);\n} catch (e) {\n  if (e instanceof BadRequestException && /Invalid conferencing app/.test(e.message)) {\n    return res.status(400).json({ code: 'use_oauth_flow', supported: [GOOGLE_MEET] });\n  }\n  throw e;\n}","preventionTips":["Maintain a client-side map of which apps require OAuth vs direct connect.","Document the connect flow per app type in your integration guide.","Validate app slugs against imported constants rather than literal strings."],"tags":["conferencing","google-meet","zoom","office365","validation","nestjs","connect"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}