nextcloud/server · error · Exception

Error importing calendar data: UID <$uid> - $errorMessage

Error message

Error importing calendar data: UID <$uid> - $errorMessage

What it means

Wraps any exception raised by the CalDavBackend while creating or updating the calendar object for a UID (createCalendarObject / updateCalendarObject) during import. ImportService catches it, and when the error mode is ERROR_FAIL rethrows it prefixed with 'Error importing calendar data: UID <uid> -' keeping the original exception as previous. In non-failing mode the message is yielded in an Error ImportObjectEvent instead.

Source

Thrown at apps/dav/lib/CalDAV/Import/ImportService.php:374

							$calendarId,
							$oid,
							$objectData
						);
						yield new ImportObjectEvent(
							disposition: ImportDisposition::Updated,
							identifier: $uid,
						);
					} else {
						yield new ImportObjectEvent(
							disposition: ImportDisposition::Exists,
							identifier: $uid,
						);
					}
				}
			} catch (Exception $e) {
				$errorMessage = $e->getMessage();
				if ($options->getErrors() === $options::ERROR_FAIL) {
					throw new Exception('Error importing calendar data: UID <' . $uid . '> - ' . $errorMessage, 0, $e);
				}
				yield new ImportObjectEvent(
					disposition: ImportDisposition::Error,
					identifier: $uid,
					errors: [$errorMessage]
				);
			}
		}
	}

	/**
	 * Validate a component
	 *
	 * @param VCalendar $vObject
	 * @param bool $repair attempt to repair the component
	 * @param int $level minimum level of issues to return
	 * @return list<mixed>
	 */

View on GitHub (pinned to ecdeb153ff)

Solutions

  1. Inspect the chained exception via getPrevious() (and your Nextcloud log) to find the real backend error before acting
  2. For duplicate/URI races, re-run the import; the getCalendarObjectByUID() lookup makes re-imports idempotent per UID
  3. Split very large imports into smaller batches and check DB health (max_allowed_packet, locks, disk space)

Example fix

// before
try {
    foreach ($service->import($source, $calendar, $options) as $event) {}
} catch (\Exception $e) {
    die($e->getMessage()); // only sees the wrapper
}

// after
try {
    foreach ($service->import($source, $calendar, $options) as $event) {}
} catch (\Exception $e) {
    $root = $e->getPrevious() ?? $e;
    $this->logger->error('Import failed for UID: ' . $root->getMessage());
}
Defensive patterns

Strategy: try-catch

Validate before calling

// nothing caller-side prevents a backend fault; check calendar writability beforehand:
if ($calendar->isReadOnly()) {
    throw new RuntimeException('calendar is read-only');
}

Try / catch

try {
    foreach ($service->import($source, $calendar, $options) as $event) {}
} catch (\Exception $e) {
    $root = $e->getPrevious() ?? $e; // real backend error
    $this->logger->error('calendar import failed', ['exception' => $root]);
    // transient DB/lock issues: safe to retry; the per-UID upsert makes it idempotent
}

Prevention

When it happens

Trigger: A backend/DB failure during import: database unreachable or lock timeout, constraint violation on the object URI, serialized data rejected by storage, or another low-level CalDavBackend error while options->getErrors() === CalendarImportOptions::ERROR_FAIL.

Common situations: Importing large files that exhaust DB connection limits or transaction time; concurrent writes to the same calendar (duplicate URI race); MariaDB/MySQL row-size limits on large calendar objects; storage quota errors.

Related errors


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