calcom/cal.diy · error · UnauthorizedException

${appleCalendar.error?.message}

Error message

${appleCalendar.error?.message}

What it means

Thrown by AppleCalendarService.checkIfCalendarConnected (apple-calendar.service.ts:54) as UnauthorizedException (HTTP 401) when the connected Apple calendar object carries a truthy error.message produced by the upstream Cal.com platform-libraries integration. The raw upstream message is re-thrown verbatim, so the actual cause (DAV 401, unreachable host, expired token) is embedded in the response body.

Source

Thrown at apps/api/v2/src/platform/calendars/services/apple-calendar.service.ts:54

    );

    if (!appleCalendarCredentials) {
      throw new BadRequestException("Credentials for apple calendar not found.");
    }

    if (appleCalendarCredentials.invalid) {
      throw new BadRequestException("Invalid apple calendar credentials.");
    }

    const { connectedCalendars } = await this.calendarsService.getCalendars(userId);
    const appleCalendar = connectedCalendars.find(
      (cal: { integration: { type: string } }) => cal.integration.type === APPLE_CALENDAR_TYPE
    );
    if (!appleCalendar) {
      throw new UnauthorizedException("Apple calendar not connected.");
    }
    if (appleCalendar.error?.message) {
      throw new UnauthorizedException(appleCalendar.error?.message);
    }

    return {
      status: SUCCESS_STATUS,
    };
  }

  async saveCalendarCredentials(userId: number, userEmail: string, username: string, password: string) {
    if (!username || !password || username.length <= 1 || password.length <= 1) {
      throw new BadRequestException(`Username or password cannot be empty`);
    }

    const existingAppleCalendarCredentials = await this.credentialRepository.getAllUserCredentialsByTypeAndId(
      APPLE_CALENDAR_TYPE,
      userId
    );

    let hasMatchingUsernameAndPassword = false;

View on GitHub (pinned to 176037d0af)

Solutions

  1. Read the dynamic message in the 401 response body — it contains the integration's verbatim error text (e.g., 'Invalid credentials').
  2. If the message is auth-related, re-save credentials (see error 361 fix).
  3. If the message indicates a network/timeout condition, retry with backoff.

Example fix

// before: surfacing only a generic error
try { await api.get('/v2/calendars/apple_calendar/check'); }
catch (e) { console.error('check failed'); }

// after: read the upstream message embedded by the service
try { await api.get('/v2/calendars/apple_calendar/check'); }
catch (e) {
  const upstreamMsg = e.response?.data?.message; // e.g. 'Invalid credentials'
  if (/credential|auth|401/i.test(upstreamMsg)) await reSaveAppleCredentials();
  else await retryWithBackoff(check);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Inspect the upstream error surfaced via the calendars list first
const { data } = await api.get('/v2/calendars');
const apple = data.connectedCalendars.find(c => c.integration?.type === 'apple_calendar');
if (apple?.error?.message) {
  // pre-handle: do not call check; the upstream error is already known
  throw new UpstreamError(apple.error.message);
}

Type guard

function hasUpstreamError(conn) {
  return typeof conn?.error?.message === 'string' && conn.error.message.length > 0;
}

Try / catch

try {
  await api.get('/v2/calendars/apple_calendar/check');
} catch (e) {
  const msg = e.response?.data?.message ?? '';
  if (e.response?.status === 401) {
    if (/auth|credential|password|401/i.test(msg)) await reSaveAppleCredentials();
    else await retryWithBackoff(() => api.get('/v2/calendars/apple_calendar/check'));
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Apple's CalDAV server returns 401 because the app-specific password was revoked; network error reaching caldav.apple.com; token/session expired inside the integration; Apple rate-limited the request.

Common situations: Transient Apple server outage; revoked app-specific password; egress/firewall blocking the CalDAV port; intermittent auth failures during high load.

Related errors


AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12). Data as JSON: /api/errors/32b9fc15a04c8131. Report an issue: GitHub.