calcom/cal.diy · error · InternalServerErrorException
Unable to fetch connected calendars events. Please try again
Error message
Unable to fetch connected calendars events. Please try again later.
What it means
Thrown by CalendarsService.getBusyTimes (calendars.service.ts:126) as InternalServerErrorException (HTTP 500) when getBusyCalendarTimes(...) returns { success: false }. The upstream Cal.com platform-libraries call could not fetch busy times from one or more providers; the underlying error detail is not propagated to the caller (diagnosability gap).
Source
Thrown at apps/api/v2/src/platform/calendars/services/calendars.service.ts:126
userId: User["id"],
dateFrom: string,
dateTo: string,
timezone: string
) {
const credentials = await this.getUniqCalendarCredentials(calendarsToLoad, userId);
const composedSelectedCalendars = await this.getCalendarsWithCredentials(
credentials,
calendarsToLoad,
userId
);
const calendarBusyTimesQuery = await getBusyCalendarTimes(
this.buildNonDelegationCredentials(credentials),
dateFrom,
dateTo,
composedSelectedCalendars
);
if (!calendarBusyTimesQuery.success) {
throw new InternalServerErrorException(
"Unable to fetch connected calendars events. Please try again later."
);
}
const calendarBusyTimesConverted = calendarBusyTimesQuery.data.map(
(busyTime: EventBusyDate & { timeZone?: string }) => {
const busyTimeStart = DateTime.fromJSDate(new Date(busyTime.start)).setZone(timezone);
const busyTimeEnd = DateTime.fromJSDate(new Date(busyTime.end)).setZone(timezone);
const busyTimeStartDate = busyTimeStart.toJSDate();
const busyTimeEndDate = busyTimeEnd.toJSDate();
return {
...busyTime,
start: busyTimeStartDate,
end: busyTimeEndDate,
};
}
);
return calendarBusyTimesConverted;
}View on GitHub (pinned to 176037d0af)
Solutions
- Retry with exponential backoff — many failures are transient provider hiccups.
- Check provider status pages and verify the user's OAuth token validity (re-connect if revoked).
- Narrow the dateFrom/dateTo range and reduce the number of calendars in calendarsToLoad.
- Inspect server logs (platform-libraries integration) for the actual failure cause, since it is not in the response.
Example fix
// before: single shot, surfaces only a generic 500
const times = await api.get('/v2/calendars/busy-times', { params });
// after: bounded retry with backoff on 500
async function getBusyTimesSafe(params, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try { return await api.get('/v2/calendars/busy-times', { params }); }
catch (e) {
if (e.response?.status !== 500 || i === attempts - 1) throw e;
await sleep(2 ** i * 500);
}
}
} Defensive patterns
Strategy: retry
Validate before calling
// Reduce blast radius before calling busy-times
const safeCalendars = calendarsToLoad.filter(c => ownedIds.has(c.credentialId));
const clipped = {
...params,
dateFrom: max(params.dateFrom, todayMinus(60)),
dateTo: min(params.dateTo, todayPlus(60)),
calendarsToLoad: safeCalendars,
};
await api.get('/v2/calendars/busy-times', { params: clipped }); Type guard
function isBusyTimesSuccess(res) {
return res?.success === true && Array.isArray(res?.data);
} Try / catch
async function getBusyTimesRetry(params, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try {
return await api.get('/v2/calendars/busy-times', { params });
} catch (e) {
if (e.response?.status !== 500 || i === attempts - 1) throw e;
await new Promise(r => setTimeout(r, 2 ** i * 500));
}
}
} Prevention
- Retry 500 busy-times failures with exponential backoff — many are transient.
- Keep dateFrom/dateTo ranges modest to avoid provider timeouts/quota.
- Log the underlying integration error server-side; the HTTP message intentionally hides it.
When it happens
Trigger: Provider (Google/Microsoft/Apple) API outage or rate limit; an expired OAuth token causes a provider 401 surfaced as failure; malformed/huge date range; network timeout to the provider.
Common situations: Google Calendar API quota exceeded; token refresh failed inside the integration; transient network blip; very wide dateFrom/dateTo window.
Related errors
- Event operations for this connection are currently only avai
- ${action} is currently only available for Google Calendar. O
- ${appleCalendar.error?.message}
- These credentials do not belong to you
- ${googleCalendar.error?.message}
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/91bdb0ba09624a95.
Report an issue: GitHub.