calcom/cal.diy · error · UnauthorizedException
Ics Feed not connected.
Error message
Ics Feed not connected.
What it means
After the ICS credential is found and not flagged invalid, IcsFeedService.check calls calendarsService.getCalendars(userId) and searches connectedCalendars for an entry whose integration.type === ICS_CALENDAR_TYPE. If none is present, the credential exists but is not wired into the user's connected-calendars list, so the request is treated as 'never connected' and UnauthorizedException('Ics Feed not connected.') is thrown (HTTP 401, not 400, because the discrepancy implies a session/state problem).
Source
Thrown at apps/api/v2/src/platform/calendars/services/ics-feed.service.ts:106
ICS_CALENDAR_TYPE,
userId
);
if (!icsFeedCredentials) {
throw new BadRequestException("Credentials for Ics Feed calendar not found.");
}
if (icsFeedCredentials.invalid) {
throw new BadRequestException("Invalid Ics Feed credentials.");
}
const { connectedCalendars } = await this.calendarsService.getCalendars(userId);
const icsCalendar = connectedCalendars.find(
(cal: { integration: { type: string } }) => cal.integration.type === ICS_CALENDAR_TYPE
);
if (!icsCalendar) {
throw new UnauthorizedException("Ics Feed not connected.");
}
if (icsCalendar.error?.message) {
throw new UnauthorizedException(icsCalendar.error?.message);
}
return {
status: SUCCESS_STATUS,
};
}
}
View on GitHub (pinned to 176037d0af)
Solutions
- Re-run POST /v2/calendars/ics/save to re-create both the credential and the calendar linkage in one transactional step.
- If the issue persists, force-bust the connected-calendars cache for that userId (the save path deletes it; a manual cache flush rules out stale reads).
- Check that the user calling /check is the same user (and same team context) that owns the linked calendar.
Defensive patterns
Strategy: validation
Validate before calling
const { connectedCalendars } = await calendarsService.getCalendars(userId);
const linked = connectedCalendars.some(c => c.integration.type === ICS_CALENDAR_TYPE);
if (!linked) {
// re-run /save to recreate the calendar linkage
} Try / catch
try {
await icsFeedService.check(userId);
} catch (e) {
if (e instanceof UnauthorizedException && e.message === 'Ics Feed not connected.') {
await icsFeedService.save(userId, userEmail, urls); // relink
} else throw e;
} Prevention
- If a save partially fails, re-save rather than calling /check.
- Bust the connected-calendars cache for the user after a save.
- Keep the userId consistent between save and check.
When it happens
Trigger: The credential row exists but the connected-calendar linkage row (selectedCalendars / destinationCalendars) was deleted or never created; a partial save that persisted the credential but failed before linking; the cache is stale and getCalendars returns a pre-add snapshot.
Common situations: A previous save partially failed between upsertUserAppCredential and the calendar-linking step; the connectedCalendars cache still serves a pre-add snapshot (note save() calls calendarsCacheService.deleteConnectedAndDestinationCalendarsCache, so a cache that wasn't cleared is the tell); user is on a different account whose credential exists but isn't linked.
Related errors
- Listed cals and URLs mismatch: ${listedCals.length} vs. ${ur
- Could not add ICS feeds, try using private ics feed.
- Credentials for Ics Feed calendar not found.
- Invalid Ics Feed credentials.
- ${icsCalendar.error?.message}
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/67ea944c9449283e.
Report an issue: GitHub.