calcom/cal.diy · error · BadRequestException

Invalid Ics Feed credentials.

Error message

Invalid Ics Feed credentials.

What it means

In IcsFeedService.check, after the credential row is found it is inspected for an `invalid` flag. Cal.com marks a credential invalid when a prior calendar operation failed (e.g. a refresh token revoked upstream, a feed that returned auth errors repeatedly). A truthy `invalid` short-circuits with BadRequestException('Invalid Ics Feed credentials.') instead of attempting the live getCalendars call.

Source

Thrown at apps/api/v2/src/platform/calendars/services/ics-feed.service.ts:97

      };
    } 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);
    }

    return {
      status: SUCCESS_STATUS,
    };
  }

View on GitHub (pinned to 176037d0af)

Solutions

  1. Re-save the ICS feed via POST /v2/calendars/ics/save with a fresh, valid URL; upsert will replace the credential and clear invalid.
  2. In the webapp, remove the broken ICS integration and re-add it so a brand-new credential row is created.
  3. If invalid flipped due to an encryption-key rotation, re-encrypt or reset the affected credential rows rather than re-adding them one by one.
Defensive patterns

Strategy: validation

Validate before calling

const cred = await credentialRepository.findCredentialByTypeAndUserId(ICS_CALENDAR_TYPE, userId);
if (cred?.invalid) {
  // prompt re-save with a fresh URL rather than calling /check
}

Try / catch

try {
  await icsFeedService.check(userId);
} catch (e) {
  if (e instanceof BadRequestException && e.message === 'Invalid Ics Feed credentials.') {
    await icsFeedService.save(userId, userEmail, freshUrls); // re-save
  } else throw e;
}

Prevention

When it happens

Trigger: The ICS feed URL changed, was made private, or was deleted on the provider side after the initial save; an earlier operation hit the credential and set its `invalid` column to true; the encryption key was rotated so the stored credential key no longer decrypts correctly and the resulting fetch fails enough times to flip invalid.

Common situations: User revoked/deleted the source calendar in Google/Outlook; CALENDSO_ENCRYPTION_KEY was rotated without re-encrypting existing credentials; long-lived credential whose feed moved behind auth.

Related errors


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