calcom/cal.diy · error · BadRequestException
Credentials for Ics Feed calendar not found.
Error message
Credentials for Ics Feed calendar not found.
What it means
Thrown by IcsFeedService.check, the connectivity-check handler. It calls credentialRepository.findCredentialByTypeAndUserId(ICS_CALENDAR_TYPE, userId); if no credential row of type 'ics_calendar' exists for that user, BadRequestException is raised because there is nothing to validate. This is a precondition gate before the more expensive getCalendars call.
Source
Thrown at apps/api/v2/src/platform/calendars/services/ics-feed.service.ts:93
teamId: credential.teamId,
appId: credential.appId,
invalid: credential.invalid,
},
};
} catch (e) {
this.logger.error("Could not add ICS feeds", e);
throw new BadRequestException("Could not add ICS feeds, try using private ics feed.");
}
}
async check(userId: number): Promise<{ status: typeof SUCCESS_STATUS }> {
const icsFeedCredentials = await this.credentialRepository.findCredentialByTypeAndUserId(
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);
}
View on GitHub (pinned to 176037d0af)
Solutions
- Run POST /v2/calendars/ics/save first to create the ICS credential, then call /check.
- Confirm the userId sent to /check is the same numeric user id returned by the save call.
- If the credential was intentionally deleted, stop polling /check or treat a 400 here as 'not configured' rather than an error.
Example fix
// before
const status = await api.get(`/v2/calendars/ics/check?userId=${userId}`);
// after
if (!icsCredentialExists) {
await api.post('/v2/calendars/ics/save', { userId, userEmail, urls });
}
const status = await api.get(`/v2/calendars/ics/check?userId=${userId}`); Defensive patterns
Strategy: validation
Validate before calling
const cred = await credentialRepository.findCredentialByTypeAndUserId(ICS_CALENDAR_TYPE, userId);
if (!cred) {
return { status: 'not_configured' }; // prompt user to save an ICS feed
} Try / catch
try {
await icsFeedService.check(userId);
} catch (e) {
if (e instanceof BadRequestException && e.message.includes('not found')) {
// treat as 'not configured' and trigger the save flow
} else throw e;
} Prevention
- Only call /check after a successful /save.
- Treat a 400 'not found' as a configuration step, not a transient error.
- Pass the exact userId returned by the save call.
When it happens
Trigger: Calling GET /v2/calendars/ics/check (or check) for a user who has never saved an ICS feed via /save; passing a userId that belongs to a different user or environment; the credential was deleted between save and check; the type string passed is not exactly ICS_CALENDAR_TYPE.
Common situations: Frontend calls /check before the user has completed /save; a user removed the ICS integration from the webapp and the client still polls /check; test/dev environment with a different userId than the one that created the credential.
Related errors
- Listed cals and URLs mismatch: ${listedCals.length} vs. ${ur
- Could not add ICS feeds, try using private ics feed.
- Invalid Ics Feed credentials.
- Ics Feed not connected.
- ${icsCalendar.error?.message}
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/95a6f2ee12ee5e3b.
Report an issue: GitHub.