nextcloud/server · warning · InvalidArgumentException
Calendar <$calendarId> doesn't support this function
Error message
Calendar <$calendarId> doesn't support this function
What it means
InvalidArgumentException thrown by occ dav:import-calendar (apps/dav/lib/Command/ImportCalendar.php:89) when the resolved calendar is not an OCA\DAV\CalDAV\CalendarImpl - i.e. it is a calendar contributed by an app through the calendar plugin/registry rather than a database-backed CalDAV calendar. Bulk import writes objects straight into the CalDAV backend, which only works for real CalDAV calendars.
Source
Thrown at apps/dav/lib/Command/ImportCalendar.php:89
$errors = is_numeric($input->getOption('errors')) ? (int)$input->getOption('errors') : null;
$validation = is_numeric($input->getOption('validation')) ? (int)$input->getOption('validation') : null;
$supersede = $input->getOption('supersede');
$showCreated = $input->getOption('show-created');
$showUpdated = $input->getOption('show-updated');
$showSkipped = $input->getOption('show-skipped');
$showErrors = $input->getOption('show-errors');
if (!$this->userManager->userExists($userId)) {
throw new InvalidArgumentException("User <$userId> not found.");
}
// retrieve calendar and evaluate if import is supported and writeable
$calendars = $this->calendarManager->getCalendarsForPrincipal('principals/users/' . $userId, [$calendarId]);
if ($calendars === []) {
throw new InvalidArgumentException("Calendar <$calendarId> not found");
}
$calendar = $calendars[0];
if (!$calendar instanceof CalendarImpl) {
throw new InvalidArgumentException("Calendar <$calendarId> doesn't support this function");
}
if (!$calendar->isWritable()) {
throw new InvalidArgumentException("Calendar <$calendarId> is not writeable");
}
if ($calendar->isDeleted()) {
throw new InvalidArgumentException("Calendar <$calendarId> is deleted");
}
// construct options object
$options = new CalendarImportOptions();
$options->setSupersede($supersede);
if ($errors !== null) {
$options->setErrors($errors);
}
if ($validation !== null) {
$options->setValidate($validation);
}
$options->setFormat($format);
$options->setCounts(true);View on GitHub (pinned to ecdeb153ff)
Solutions
- Import into a regular CalDAV calendar (one the user can edit in the Calendar app)
- Create a fresh calendar as import target if needed
- For app calendars, use the app's own import path
Defensive patterns
Strategy: type-guard
Validate before calling
$calendars = $calendarManager->getCalendarsForPrincipal('principals/users/' . $uid, [$uri]);
if (!$calendars[0] instanceof \OCA\DAV\CalDAV\CalendarImpl) {
throw new RuntimeException('Target is not an importable CalDAV calendar');
} Type guard
$isImportable = fn ($c): bool => $c instanceof \OCA\DAV\CalDAV\CalendarImpl;
Prevention
- Only CalDAV-backed calendars accept bulk import
- App calendars expose data read-only; use their own import tooling
- Check the calendar source before scripting imports
When it happens
Trigger: occ dav:import-calendar alice <uri> ... where <uri> resolves to an ICalendar provided by an app (external/plugin calendar), not to CalendarImpl.
Common situations: Trying to import into read-only app calendars (e.g. birthday or app-generated calendars); custom apps registering ICalendar implementations expecting them to be importable.
Related errors
- Calendar <$calendarId> does not support exporting
- User <$userId> not found.
- Calendar <$calendarId> not found
- Calendar <$calendarId> is not writeable
- Calendar <$calendarId> is deleted
AI-assisted analysis of nextcloud/server@ecdeb153ff (2026-08-17).
Data as JSON: /api/errors/0e8fc9a221597c05.
Report an issue: GitHub.