nextcloud/server · warning · InvalidArgumentException

Calendar <$calendarId> does not support exporting

Error message

Calendar <$calendarId> does not support exporting

What it means

InvalidArgumentException thrown by occ dav:export-calendar (apps/dav/lib/Command/ExportCalendar.php:70) when the resolved calendar object does not implement OCP\Calendar\ICalendarExport. Only Nextcloud's own CalDAV calendars (CalendarImpl) know how to serialize to iCal/jCal/xCal; calendars contributed by apps via the calendar registry may not support export.

Source

Thrown at apps/dav/lib/Command/ExportCalendar.php:70

	#[\Override]
	protected function execute(InputInterface $input, OutputInterface $output): int {
		$userId = $input->getArgument('uid');
		$calendarId = $input->getArgument('uri');
		$format = $input->getOption('format');
		$location = $input->getOption('location');

		if (!$this->userManager->userExists($userId)) {
			throw new InvalidArgumentException("User <$userId> not found.");
		}
		// retrieve calendar and evaluate if export is supported
		$calendars = $this->calendarManager->getCalendarsForPrincipal('principals/users/' . $userId, [$calendarId]);
		if ($calendars === []) {
			throw new InvalidArgumentException("Calendar <$calendarId> not found.");
		}
		$calendar = $calendars[0];
		if (!$calendar instanceof ICalendarExport) {
			throw new InvalidArgumentException("Calendar <$calendarId> does not support exporting");
		}
		// construct options object
		$options = new CalendarExportOptions();
		// evaluate if provided format is supported
		if (!in_array($format, ExportService::FORMATS, true)) {
			throw new InvalidArgumentException("Format <$format> is not valid.");
		}
		$options->setFormat($format);
		// evaluate if a valid location was given and is usable otherwise output to stdout
		if ($location !== null) {
			$handle = fopen($location, 'wb');
			if ($handle === false) {
				throw new InvalidArgumentException("Location <$location> is not valid. Cannot open location for write operation.");
			}

			foreach ($this->exportService->export($calendar, $options) as $chunk) {
				fwrite($handle, $chunk);
			}

View on GitHub (pinned to ecdeb153ff)

Solutions

  1. Export only CalDAV-backed calendars (those visible under /remote.php/dav/calendars/<uid>/)
  2. For app-provided read-only calendars, use that app's own export if any
  3. Confirm the target with PROPFIND on the CalDAV home before choosing the uri argument
Defensive patterns

Strategy: type-guard

Validate before calling

$calendars = $calendarManager->getCalendarsForPrincipal('principals/users/' . $uid, [$uri]);
$exportable = array_filter($calendars, fn ($c) => $c instanceof \OCP\Calendar\ICalendarExport);

Type guard

$isExportable = fn ($calendar): bool => $calendar instanceof \OCP\Calendar\ICalendarExport;

Try / catch

try { $command->run(...); }
catch (\InvalidArgumentException $e) {
    if (str_contains($e->getMessage(), 'does not support exporting')) {
        // target an app-internal export or a real CalDAV calendar
    }
}

Prevention

When it happens

Trigger: occ dav:export-calendar alice <uri> where <uri> resolves to a plugin/external calendar (e.g. a read-only app calendar registered via ICalendarProvider) rather than a database-backed CalDAV calendar.

Common situations: App-provided calendars (birthday calendars from contacts apps, external app calendars); trying to export 'contact_birthdays'; custom apps registering ICalendar implementations without export support.

Related errors


AI-assisted analysis of nextcloud/server@ecdeb153ff (2026-08-17). Data as JSON: /api/errors/d6a56809c3c5f97f. Report an issue: GitHub.