{"record":{"id":"8422711c15e8e32d","repo":"calcom/cal.diy","slug":"failed-to-update-meeting-details","errorCode":null,"errorMessage":"Failed to update meeting details","messagePattern":"Failed to update meeting details","errorType":"http","errorClass":"NotFoundException","httpStatus":404,"severity":"error","filePath":"apps/api/v2/src/modules/cal-unified-calendars/services/google-calendar.service.ts","lineNumber":99,"sourceCode":"      bookingReference.credential?.key,\n      bookingReference.delegationCredential\n    );\n\n    const updatePayload = new GoogleCalendarEventInputPipe().transform(updateData);\n\n    try {\n      const event = await calendar.events.patch({\n        calendarId: bookingReference?.externalCalendarId ?? \"primary\",\n        eventId: bookingReference?.uid,\n        requestBody: updatePayload,\n      });\n\n      if (!event.data) {\n        throw new NotFoundException(\"Failed to update meeting\");\n      }\n      return event.data as GoogleCalendarEventResponse;\n    } catch (error) {\n      throw new NotFoundException(\"Failed to update meeting details\");\n    }\n  }\n\n  /**\n   * Gets an authorized Google Calendar instance\n   * Tries delegation credentials first, falls back to direct OAuth\n   */\n  private async getAuthorizedCalendarInstance(\n    userEmail?: string,\n    oAuthCredentials?: Prisma.JsonValue | undefined,\n    delegationCredential?: { id: string } | null\n  ): Promise<calendar_v3.Calendar> {\n    if (userEmail && delegationCredential?.id) {\n      const delegatedCalendar = await this.getDelegatedCalendarInstance(delegationCredential, userEmail);\n      if (delegatedCalendar) {\n        return delegatedCalendar;\n      }\n    }","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/apps/api/v2/src/modules/cal-unified-calendars/services/google-calendar.service.ts#L81-L117","documentation":"GoogleCalendarService.updateEventDetails wraps the calendar.events.patch call in try/catch and rethrows as NotFoundException('Failed to update meeting details'). Any error from the Google API during the patch (auth, validation, quota, 404) is collapsed into this single message, masking the real cause.","triggerScenarios":"Google Calendar API rejects the patch: 400 invalid field values, 401/403 credential or scope problems, 404 event/calendar gone, 429 quota, 5xx transient.","commonSituations":"Patch payload violates Google's schema (e.g. invalid attendee email, bad timestamp); credential's refresh token expired; missing calendar.events scope; rate-limited.","solutions":["Log the underlying error before rethrowing so the cause is diagnosable (today it is swallowed).","Validate the patch payload with GoogleCalendarEventInputPipe output schema before sending.","Re-authenticate the Google connection for 401/403; retry with backoff on 429/5xx.","Improve the catch to distinguish 400 (bad payload) from 404 (gone) from 5xx (upstream)."],"exampleFix":"// before\n} catch (error) {\n  throw new NotFoundException(\"Failed to update meeting details\");\n}\n\n// after\n} catch (error) {\n  this.logger.error({ message: 'gcal events.patch failed', eventId, error });\n  const status = error?.code ?? error?.response?.status;\n  if (status === 400) throw new BadRequestException('Invalid event update payload for Google Calendar');\n  if (status === 401 || status === 403) throw new UnauthorizedException('Google Calendar access denied');\n  if (status === 404) throw new NotFoundException('Meeting not found in Google Calendar');\n  throw new BadGatewayException('Failed to update meeting in Google Calendar');\n}","handlingStrategy":"try-catch","validationCode":"// Validate the patch payload against Google's schema before sending\nconst clean = stripUnknownFields(patch, ['summary','description','start','end','attendees','location']);\nassertValidGoogleEventPatch(clean);","typeGuard":null,"tryCatchPattern":"try {\n  return await api.v2.calUnified.updateEvent(eventUid, patch);\n} catch (err) {\n  if (err?.statusCode === 404 && /Failed to update meeting details/i.test(err?.message)) {\n    // ambiguous: could be auth, payload, quota, or upstream. Log + escalate; do NOT blindly retry.\n    throw new Error('Update failed at Google Calendar; check credentials, payload, and quota.');\n  }\n  throw err;\n}","preventionTips":["Patch the service to log the underlying Google error and map status codes to distinct responses.","Validate the patch payload with the input pipe's schema before sending.","Re-authenticate the Google connection on 401/403; back off on 429/5xx."],"tags":["calendar","google-calendar","error-handling","update","api-v2"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}