calcom/cal.diy · error · BadRequestException
Credentials for office_365_calendar not found.
Error message
Credentials for office_365_calendar not found.
What it means
Thrown by OutlookService.checkIfCalendarConnected. It looks up the user's credential row of type 'office365_calendar' via credentialRepository.findCredentialByTypeAndUserId('office365_calendar', userId). If no such row exists, BadRequestException is raised: the user has never connected an Office 365 calendar, so the connectivity check has nothing to evaluate. This mirrors the structure of the Google and ICS check methods.
Source
Thrown at apps/api/v2/src/platform/calendars/services/outlook.service.ts:95
redirect_uri: this.redirectUri,
state: JSON.stringify(state),
};
const query = stringify(params);
const url = `https://login.microsoftonline.com/common/oauth2/v2.0/authorize?${query}`;
return url;
}
async checkIfCalendarConnected(userId: number): Promise<{ status: typeof SUCCESS_STATUS }> {
const office365CalendarCredentials = await this.credentialRepository.findCredentialByTypeAndUserId(
"office365_calendar",
userId
);
if (!office365CalendarCredentials) {
throw new BadRequestException("Credentials for office_365_calendar not found.");
}
if (office365CalendarCredentials.invalid) {
throw new BadRequestException("Invalid office 365 calendar credentials.");
}
const { connectedCalendars } = await this.calendarsService.getCalendars(userId);
const office365Calendar = connectedCalendars.find(
(cal: { integration: { type: string } }) => cal.integration.type === OFFICE_365_CALENDAR_TYPE
);
if (!office365Calendar) {
throw new UnauthorizedException("Office 365 calendar not connected.");
}
if (office365Calendar.error?.message) {
throw new UnauthorizedException(office365Calendar.error?.message);
}
return {View on GitHub (pinned to 176037d0af)
Solutions
- Run the Office 365 connect flow (saveCalendarCredentialsAndRedirect) first so a credential row of type 'office365_calendar' is created.
- Confirm the userId sent to /check is the numeric id of the user who completed connect.
- Treat a 400 from /check as 'not configured' on the client and prompt the user to connect.
Defensive patterns
Strategy: validation
Validate before calling
const cred = await credentialRepository.findCredentialByTypeAndUserId('office365_calendar', userId);
if (!cred) {
return { status: 'not_configured' }; // prompt user to connect Office 365
} Try / catch
try {
await outlookService.checkIfCalendarConnected(userId);
} catch (e) {
if (e instanceof BadRequestException && e.message.includes('not found')) {
// trigger the Office 365 connect flow
} else throw e;
} Prevention
- Run the Office 365 connect flow before calling /check.
- Pass the exact userId that completed connect.
- Treat a 400 'not found' as 'not configured', not a transient error.
When it happens
Trigger: Calling GET /v2/calendars/office365/check for a user who never completed the Office 365 OAuth connect flow; passing the wrong userId; the credential was deleted from the webapp's integrations page; the type literal 'office365_calendar' is mismatched against what was actually saved (e.g. a legacy 'outlook' type).
Common situations: Frontend polls /check before /connect completes; test/dev environment mismatch; a user removed the Office 365 integration and the client keeps polling; account switch where the new user has no O365 credential.
Related errors
- Credentials for Ics Feed calendar not found.
- Invalid office 365 calendar credentials.
- Office 365 calendar not connected.
- ${office365Calendar.error?.message}
- Invalid Access token.
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/c964a41143dfd110.
Report an issue: GitHub.