Skip to content

[BUG] Google Calendar PATCH requests excluded from retry logic, causing silent booking/calendar desync #28834

@aribn

Description

@aribn

Issue Summary

When a booking is created through Cal.com, the Google Calendar integration makes multiple sequential API calls (event creation, then PATCH to update description/location/conference data). If the PATCH call is rejected by Google with a 403 Rate Limit Exceeded error, Cal.com does not retry the request due to two gaps in the gaxios retry configuration:

  1. PATCH is excluded from httpMethodsToRetry — only GET, HEAD, PUT, OPTIONS, and DELETE are retried. PATCH and POST are not.
  2. HTTP 403 is excluded from statusCodesToRetry — only [100-199], [429], and [500-599] are retried. Google's [error handling docs](https://developers.google.com/workspace/calendar/api/guides/errors) state that rateLimitExceeded can return either 403 or 429, and both should be handled with exponential backoff.

Because of these two gaps, a transient rate limit error on a PATCH request is never retried. The calendar event update is permanently lost, but the booking still appears successful in Cal.com's database and UI, and downstream workflow tasks (like reminder emails) are still queued.

The retryConfig seen in the logs may be the default from gaxios (the HTTP client inside google-auth-library) rather than something Cal.com explicitly sets. If so, the fix would involve Cal.com explicitly passing a custom retryConfig when instantiating the Google Calendar API client to override these defaults.

Steps to Reproduce

  1. Self-host Cal.com (v6.2.0 via Cloudron package com.cal.cloudronapp@2.13.0) with Google Calendar integration connected
  2. A booking is created via the booking page, triggering a Google Calendar event
  3. The initial event creation (POST/insert) succeeds, but the follow-up PATCH (to add description, location, and Google Meet conference data) is rejected by Google with a 403 Rate Limit Exceeded error
  4. Cal.com logs BookingCreatingMeetingFailed but still queues workflow reminder emails for the booking
  5. The booking appears on the Cal.com dashboard with no indication of failure

This is more likely to occur on self-hosted instances using their own Google Cloud API project, which may have lower default per-user burst rate limits than Cal.com's hosted infrastructure. The Google Cloud Console quotas dashboard may not show any limit being hit, because these are short-burst per-user rate limits that don't appear in the daily aggregate view.

Actual Results

  • The PATCH request to Google Calendar fails with 403 Rate Limit Exceeded and is not retried (currentRetryAttempt: 0 stays at 0)
  • Cal.com logs BookingCreatingMeetingFailed server-side
  • The Google Calendar event is either missing or in an incomplete/partial state (no description, no Meet link, possibly no attendee notification sent)
  • The booking still appears as successful in Cal.com's UI
  • Workflow reminder emails are still queued and will be sent to the attendee — for a meeting that may not be on either party's calendar
  • If the organizer later tries to reschedule this booking, that also fails because Cal.com tries to update a calendar event that doesn't fully exist (see Improvement: Rescheduling of a booking that had earlier failed to create Calendar event #22192)

Expected Results

  • The PATCH request should be retried with exponential backoff on 403 rateLimitExceeded errors, per Google's own API documentation
  • If all retries are exhausted and the calendar event still can't be created/updated, the failure should be surfaced to the organizer in Cal.com's UI
  • Workflow emails (reminders) should not be queued for bookings where the calendar event creation has failed, or should be queued conditionally

Technical details

  • Cal.com version: 6.2.0
  • Cloudron package: com.cal.cloudronapp@2.13.0
  • Node.js: v22.14.0
  • google-api-nodejs-client: 7.0.1
  • google-auth-library/gaxios: (retry logic lives here)
  • Google Calendar API: v3

The retry configuration from the error response:

"retryConfig": {
  "currentRetryAttempt": 0,
  "retry": 3,
  "httpMethodsToRetry": ["GET", "HEAD", "PUT", "OPTIONS", "DELETE"],
  "noResponseRetries": 2,
  "statusCodesToRetry": [[100, 199], [429, 429], [500, 599]]
}

Two fixes are needed:

  • Add "PATCH" and "POST" to httpMethodsToRetry
  • Add [403, 403] to statusCodesToRetry

The relevant code is likely in packages/app-store/googlecalendar/lib/CalendarService.ts or wherever the Google API client is instantiated. If Cal.com is not explicitly setting a retryConfig, it would need to start overriding the gaxios defaults.

Evidence

Sanitized server logs from Cloudron showing the full error chain:

1. Google Calendar API rejects the PATCH with 403:

CalendarService: There was an error creating event in google calendar:
{
  "error": {
    "config": {
      "url": "https://www.googleapis.com/calendar/v3/calendars/{calendar}/events/{event_id}",
      "method": "PATCH",
      "retryConfig": {
        "currentRetryAttempt": 0,
        "retry": 3,
        "httpMethodsToRetry": ["GET", "HEAD", "PUT", "OPTIONS", "DELETE"],
        "noResponseRetries": 2,
        "statusCodesToRetry": [[100,199], [429,429], [500,599]]
      }
    },
    "response": {
      "data": {
        "error": {
          "errors": [{ "domain": "usageLimits", "reason": "rateLimitExceeded", "message": "Rate Limit Exceeded" }],
          "code": 403,
          "message": "Rate Limit Exceeded"
        }
      },
      "status": 403
    }
  }
}

2. CalendarManager reports the failure:

CalendarManager: createEvent failed
"Error: Rate Limit Exceeded at Gaxios._request ..."

3. EventManager logs the integration failure:

EventManager.create failure in some of the integrations
{
  "error": { "errorCode": "BookingCreatingMeetingFailed", "message": "Booking failed" },
  "results": [{ "appName": "Google Calendar", "type": "google_calendar", "success": false }]
}

4. But the workflow reminder email is still queued:

Creating task {
  type: 'sendWorkflowEmails',
  payload: '{"subject":"Reminder: ...","to":["attendee@example.com"]}',
  scheduledAt: 2026-04-13T15:00:00.000Z
}

Related Issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    🐛 bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions