nextcloud/server · error · InvalidArgumentException

Error importing calendar data: One or more objects discovere

Error message

Error importing calendar data: One or more objects discovered without a UID

What it means

Thrown when the first base component of an imported object has no UID property. The UID is mandatory for VEVENT/VTODO/VJOURNAL per RFC 5545 and is used by the backend to find and deduplicate existing objects, so ImportService refuses such objects when the error mode is ERROR_FAIL. Otherwise it yields an ImportObjectEvent with disposition Error and identifier null.

Source

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

					if ($type !== $entry->name) {
						$errorMessage = 'One or more objects discovered with multiple base component types';
						if ($options->getErrors() === $options::ERROR_FAIL) {
							throw new InvalidArgumentException('Error importing calendar data: ' . $errorMessage);
						}
						yield new ImportObjectEvent(
							disposition: ImportDisposition::Error,
							identifier: null,
							errors: [$errorMessage]
						);
						continue 2;
					}
				}
			}
			// determine if the object has a uid
			if (!isset($components[0]->UID)) {
				$errorMessage = 'One or more objects discovered without a UID';
				if ($options->getErrors() === $options::ERROR_FAIL) {
					throw new InvalidArgumentException('Error importing calendar data: ' . $errorMessage);
				}
				yield new ImportObjectEvent(
					disposition: ImportDisposition::Error,
					identifier: null,
					errors: [$errorMessage]
				);
				continue;
			}
			$uid = $components[0]->UID->getValue();
			// validate object
			if ($options->getValidate() !== $options::VALIDATE_NONE) {
				$issues = $this->componentValidate($vObject, true, 3);
				if ($options->getValidate() === $options::VALIDATE_SKIP && $issues !== []) {
					yield new ImportObjectEvent(
						disposition: ImportDisposition::Error,
						identifier: $uid,
						errors: $issues
					);

View on GitHub (pinned to ecdeb153ff)

Solutions

  1. Add a stable UID to every base component before importing (a UUID is fine, e.g. via \Sabre\VObject\UUIDUtil::getUUID())
  2. Import with errors below ERROR_FAIL and treat the yielded Error events as a skip list, fixing UIDs later
  3. Pre-validate each component with isset($component->UID) before calling import()

Example fix

// before
BEGIN:VEVENT
SUMMARY:Standup
END:VEVENT

// after
BEGIN:VEVENT
UID:5f9c2b7a-2f4e-4c1a-9d3b-8a1e6f0d7c22
SUMMARY:Standup
END:VEVENT
Defensive patterns

Strategy: validation

Validate before calling

$v = \Sabre\VObject\Reader::read($ics);
foreach ($v->getBaseComponents() as $c) {
    if (!isset($c->UID)) {
        $c->UID = \Sabre\VObject\UUIDUtil::getUUID();
    }
}

Type guard

function hasUid(\Sabre\VObject\Component $c): bool {
    return isset($c->UID) && $c->UID->getValue() !== '';
}

Try / catch

try {
    foreach ($service->import($source, $calendar, $options) as $event) {}
} catch (\InvalidArgumentException $e) {
    // message names the object; assign UIDs in source and retry
}

Prevention

When it happens

Trigger: Importing a calendar object whose VEVENT/VTODO/VJOURNAL lacks a UID line (e.g. 'BEGIN:VEVENT\nSUMMARY:x\nEND:VEVENT') while options->getErrors() === CalendarImportOptions::ERROR_FAIL.

Common situations: Hand-written test .ics files; data from broken exporters or spreadsheets converted to iCal; lines lost during manual editing or encoding conversions (UID folded or mangled).

Related errors


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