calcom/cal.diy · error · UnauthorizedException
These credentials do not belong to you
Error message
These credentials do not belong to you
What it means
Thrown by CalendarsService.getUniqCalendarCredentials (calendars.service.ts:151) as UnauthorizedException (HTTP 401) when getUserCredentialsByIds(userId, uniqueCredentialIds) returns fewer rows than the number of unique credentialIds requested. At least one credentialId in calendarsToLoad is absent or belongs to another user (the query filters by userId).
Source
Thrown at apps/api/v2/src/platform/calendars/services/calendars.service.ts:151
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;
}
async getUniqCalendarCredentials(calendarsToLoad: Calendar[], userId: User["id"]) {
const uniqueCredentialIds = Array.from(new Set(calendarsToLoad.map((item) => item.credentialId)));
const credentials = await this.credentialsRepository.getUserCredentialsByIds(userId, uniqueCredentialIds);
if (credentials.length !== uniqueCredentialIds.length) {
throw new UnauthorizedException("These credentials do not belong to you");
}
return credentials;
}
async getCalendarsWithCredentials(
credentials: CredentialsWithUserEmail,
calendarsToLoad: Calendar[],
userId: User["id"]
) {
const composedSelectedCalendars = calendarsToLoad.map((calendar) => {
const credential = credentials.find((item) => item.id === calendar.credentialId);
if (!credential) {
throw new UnauthorizedException("These credentials do not belong to you");
}
return {
...calendar,
userId,View on GitHub (pinned to 176037d0af)
Solutions
- Only pass credentialIds returned by GET /v2/calendars for the currently authenticated user.
- Filter calendarsToLoad client-side to ids present in the user's connectedCalendars before calling busy-times.
- Treat a 401 here as a security signal — do not silently retry with the same ids.
Example fix
// before: passing whatever ids the client holds
await api.get('/v2/calendars/busy-times', { params: { calendarsToLoad } }); // 401
// after: intersect with the user's own credential ids
const { data } = await api.get('/v2/calendars');
const owned = new Set(data.connectedCalendars.map(c => c.credentialId));
const safe = calendarsToLoad.filter(c => owned.has(c.credentialId));
await api.get('/v2/calendars/busy-times', { params: { calendarsToLoad: safe } }); Defensive patterns
Strategy: validation
Validate before calling
// Intersect requested ids with the user's own credentials before busy-times
const { data } = await api.get('/v2/calendars');
const owned = new Set(data.connectedCalendars.map(c => c.credentialId));
const safe = calendarsToLoad.filter(c => owned.has(c.credentialId));
if (safe.length !== calendarsToLoad.length) {
throw new Error('Some credentialIds are not owned by this user');
}
await api.get('/v2/calendars/busy-times', { params: { ...params, calendarsToLoad: safe } }); Type guard
function allOwned(requestedIds, ownedIds) {
return requestedIds.every((id) => ownedIds.has(id));
} Try / catch
try {
await api.get('/v2/calendars/busy-times', { params });
} catch (e) {
if (e.response?.status === 401 && /do not belong/i.test(e.response?.data?.message)) {
// security signal — do NOT retry with the same ids; refresh ownership
await refreshCalendarList();
throw new AuthorizationError('credentialId ownership mismatch');
}
throw e;
} Prevention
- Only pass credentialIds returned by GET /v2/calendars for the current user.
- Treat a 401 'do not belong to you' as a security event — never silently retry.
- Clear cached credentialIds on logout/account switch.
When it happens
Trigger: GET /v2/calendars/busy-times with a calendarsToLoad[].credentialId belonging to another user; a deleted credential id; a fabricated/guessed id; stale id cached client-side after re-connecting a different account.
Common situations: Client caches credentialIds across account switches; multi-tenant mix-up; frontend retained an id after the user re-authenticated as someone else.
Related errors
- ApiKeysService - This endpoint can only be accessed using an
- Event type with id ${eventTypeId} not found
- Access denied. Either the team with ID=${teamId} does not ow
- PermissionsGuard - oAuth client with id=${oAuthClient.id} do
- No valid credentials available for Google Calendar
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/0589bd2832e3f797.
Report an issue: GitHub.