{"record":{"id":"9a83a883dfc91edd","repo":"calcom/cal.diy","slug":"could-not-load-booking-details-for-uid-existingb","errorCode":null,"errorMessage":"Could not load booking details for uid=${existingBooking.uid}","messagePattern":"Could not load booking details for uid=(.+?)","errorType":"http","errorClass":"NotFoundException","httpStatus":404,"severity":"error","filePath":"apps/api/v2/src/platform/bookings/2024-08-13/services/booking-location-integration.service.ts","lineNumber":86,"sourceCode":"    inputLocation: { type: \"integration\"; integration: Integration_2024_08_13 },\n    user: ApiAuthGuardUser,\n    existingBookingHost: { organizationId: number | null } | null\n  ): Promise<BookingLocationResponse> {\n    if (!existingBookingHost) {\n      throw new NotFoundException(`No user found for booking with uid=${existingBooking.uid}`);\n    }\n\n    const integrationSlug = inputLocation.integration;\n    const internalLocation =\n      apiToInternalintegrationsMapping[integrationSlug as keyof typeof apiToInternalintegrationsMapping];\n\n    if (!internalLocation) {\n      throw new BadRequestException(`Unsupported integration: ${integrationSlug}`);\n    }\n\n    const booking = await this.bookingsRepository.getBookingByIdWithUserAndEventDetails(existingBooking.id);\n    if (!bookingHasUser(booking)) {\n      throw new NotFoundException(`Could not load booking details for uid=${existingBooking.uid}`);\n    }\n\n    const ctx: IntegrationHandlerContext = {\n      existingBooking,\n      booking,\n      integrationSlug,\n      internalLocation,\n      user,\n      existingBookingHost,\n      inputLocation,\n    };\n\n    switch (integrationSlug) {\n      case \"google-meet\":\n        return this.handleGoogleMeetLocation(ctx);\n      case \"office365-video\":\n        return this.handleMSTeamsLocation(ctx);\n      case \"cal-video\":","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/apps/api/v2/src/platform/bookings/2024-08-13/services/booking-location-integration.service.ts#L68-L104","documentation":"Thrown by handleIntegrationLocationUpdate when re-fetching the booking by its numeric ID (getBookingByIdWithUserAndEventDetails) fails the bookingHasUser type guard. That guard returns false when the re-fetched booking is null OR its user relation is null. The integration location handlers all require a host user (to read credentials and build the calendar event), so a missing user is fatal. It surfaces as HTTP 404 NotFoundException even though the root cause is usually a data-integrity gap rather than a wrong UID.","triggerScenarios":"PATCH /v2/bookings/{uid} (or the 2024-08-13 equivalent) with body location.type = \"integration\" (e.g. zoom, google-meet, cal-video) for a booking row whose user relation is null, or for a booking that gets deleted between the initial UID lookup and the ID re-fetch inside handleIntegrationLocationUpdate.","commonSituations":"Orphaned/legacy bookings where userId is set but the user record was deleted; bookings created by background jobs without an owner; race condition where the booking is cancelled/deleted mid-request; seeded test data without a linked user.","solutions":["GET the booking first and confirm it has a non-null user/owner before sending the integration PATCH.","If the booking is orphaned, reassign booking.userId to a valid user via the DB/admin tooling, then retry.","Verify the booking UID is correct and that the booking has not been deleted between the GET and the PATCH.","If reproducing in tests, create the booking through the normal booking flow so a user is always attached."],"exampleFix":"// before: PATCH /v2/bookings/{uid}/location with location.type=integration on an orphaned booking\n// after: verify host user exists before updating\nconst booking = await api.get(`/v2/bookings/${uid}`);\nif (!booking.user) {\n  // reassign or skip integration update; booking has no host to source credentials from\n  throw new Error(`Booking ${uid} has no host user; cannot set integration location`);\n}\nawait api.patch(`/v2/bookings/${uid}/location`, { location: { type: 'integration', integration: 'zoom' } });","handlingStrategy":"validation","validationCode":"// Before PATCHing location to an integration, confirm the booking has a host user.\nconst booking = await api.get(`/v2/bookings/${uid}`);\nif (!booking) throw new Error(`Booking ${uid} not found`);\nif (!booking.user) throw new Error(`Booking ${uid} has no host user; cannot use integration location`);","typeGuard":"function bookingHasHostUser(b: { user: unknown } | null | undefined): b is { user: Record<string, unknown> } {\n  return !!b && !!b.user && typeof b.user === 'object';\n}","tryCatchPattern":"try {\n  await api.patch(`/v2/bookings/${uid}/location`, { location: { type: 'integration', integration } });\n} catch (err) {\n  if (err.status === 404 && /Could not load booking details/.test(err.message)) {\n    // booking has no host user; reassign owner or fall back to a non-integration location\n  }\n  throw err;\n}","preventionTips":["Always create bookings through the standard booking flow so a host user is attached.","Before an integration location PATCH, GET the booking and assert it has a non-null user.","Never null out booking.userId in migrations without reassigning bookings."],"tags":["booking","integration","data-integrity","not-found"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}