{"record":{"id":"3f206ca13a2d550b","repo":"calcom/cal.diy","slug":"calendar-connection-not-found","errorCode":null,"errorMessage":"Calendar connection not found","messagePattern":"Calendar connection not found","errorType":"http","errorClass":"NotFoundException","httpStatus":404,"severity":"error","filePath":"apps/api/v2/src/modules/cal-unified-calendars/services/google-calendar.service.ts","lineNumber":196,"sourceCode":"    }\n    if (credential.invalid) {\n      throw new UnauthorizedException(\"Google Calendar credentials are invalid. Please reconnect.\");\n    }\n    return this.getAuthorizedCalendarInstance(\n      credential.user?.email ?? undefined,\n      credential.key,\n      credential.delegationCredentialId ? { id: credential.delegationCredentialId } : null\n    );\n  }\n\n  /**\n   * Gets an authorized Google Calendar instance for a specific credential (connection).\n   * Tries delegated auth first (if available), then falls back to direct OAuth.\n   */\n  async getCalendarClientByCredentialId(userId: number, credentialId: number): Promise<calendar_v3.Calendar> {\n    const credential = await this.credentialsRepository.findCredentialByIdAndUserId(credentialId, userId);\n    if (!credential) {\n      throw new NotFoundException(\"Calendar connection not found\");\n    }\n    if (credential.type !== GOOGLE_CALENDAR_TYPE) {\n      throw new BadRequestException(\n        \"Event operations for this connection are currently only available for Google Calendar\"\n      );\n    }\n    if (credential.invalid) {\n      throw new UnauthorizedException(\"Calendar credentials are invalid. Please reconnect.\");\n    }\n    return this.getAuthorizedCalendarInstance(\n      credential.user?.email ?? undefined,\n      credential.key,\n      credential.delegationCredentialId ? { id: credential.delegationCredentialId } : null\n    );\n  }\n\n  // ─── Shared private helpers (DRY calendar CRUD) ──────────────────────\n","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/apps/api/v2/src/modules/cal-unified-calendars/services/google-calendar.service.ts#L178-L214","documentation":"Thrown by getCalendarClientByCredentialId when findCredentialByIdAndUserId(credentialId, userId) returns null — the supplied credentialId does not exist OR does not belong to the supplied userId. Returns HTTP 404 via NotFoundException. This is the connection-scoped entry point (listConnectionEvents, createConnectionEvent, etc.).","triggerScenarios":"Calling any /v2/calendars/connections/{connectionId}/... endpoint with a connectionId that is stale, deleted, belongs to another user, or was transposed (typo). Also triggered when a team/org credential is referenced by userId when the query filters by owner.","commonSituations":"Frontend cached an old connection list after the user disconnected; cross-tenant access attempt; integer parsing of connectionId produced a wrong value; the connection was deleted in another session.","solutions":["Refresh the connections list via GET /v2/calendars/connections and use a current connectionId.","Confirm the credentialId belongs to the calling user: SELECT id, \"userId\" FROM \"AppCredential\" WHERE id=? AND \"userId\"=?.","If the credential was deleted, instruct the user to reconnect and obtain a new connectionId.","Validate that connectionId is a positive integer before the request."],"exampleFix":"// before\nconst event = await googleCalendarService.getEventByConnectionId(userId, Number(connectionId), calId, evId);\n\n// after\nconst connectionIdNum = Number(connectionId);\nif (!Number.isInteger(connectionIdNum) || connectionIdNum <= 0) {\n  throw new BadRequestException('connectionId must be a positive integer.');\n}\nconst cred = await credentialsRepository.findCredentialByIdAndUserId(connectionIdNum, userId);\nif (!cred) {\n  throw new NotFoundException(`No calendar connection ${connectionIdNum} for user ${userId}.`);\n}","handlingStrategy":"validation","validationCode":"function parseConnectionId(raw: string): number {\n  const n = Number(raw);\n  if (!Number.isInteger(n) || n <= 0) {\n    throw new BadRequestException('connectionId must be a positive integer.');\n  }\n  return n;\n}\n\nasync function connectionBelongsToUser(connectionId: number, userId: number): Promise<boolean> {\n  const cred = await credentialsRepository.findCredentialByIdAndUserId(connectionId, userId);\n  return Boolean(cred);\n}\n\nconst id = parseConnectionId(req.params.connectionId);\nif (!(await connectionBelongsToUser(id, userId))) {\n  throw new NotFoundException('Calendar connection not found.');\n}","typeGuard":"function isPositiveInt(n: unknown): n is number {\n  return typeof n === 'number' && Number.isInteger(n) && n > 0;\n}","tryCatchPattern":"try {\n  return await googleCalendarService.getEventByConnectionId(userId, credentialId, calId, evId);\n} catch (e) {\n  if (e instanceof NotFoundException && /not found/i.test(e.message)) {\n    return res.status(404).json({ code: 'connection_not_found', connectionId });\n  }\n  throw e;\n}","preventionTips":["Always type-coerce and range-check connectionId at the controller boundary.","Refresh the client connection list after any disconnect/reconnect to avoid stale ids.","Never accept connectionId from an untrusted source without an ownership check."],"tags":["google-calendar","credentials","nestjs","not-found","connection"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}