nextcloud/server · error · InvalidArgumentException

Error importing calendar data: UID <$uid> - $issues[0]

Error message

Error importing calendar data: UID <$uid> - $issues[0]

What it means

Thrown when CalendarImportOptions::VALIDATE_FAIL is set and sabre/vobject validation (wrapped by ImportService::componentValidate(), depth 3, 4.0 semantics) reports at least one issue for the object being imported. The message embeds the UID and the first validation issue, e.g. a VEVENT without DTSTART or an invalid RRULE. With the default VALIDATE_SKIP the object is not thrown but yielded as an Error event; VALIDATE_NONE disables the check entirely.

Source

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

					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
					);
					continue;
				} elseif ($options->getValidate() === $options::VALIDATE_FAIL && $issues !== []) {
					throw new InvalidArgumentException('Error importing calendar data: UID <' . $uid . '> - ' . $issues[0]);
				}
			}
			// create or update object in the data store
			$objectId = $this->backend->getCalendarObjectByUID($principalUri, $uid, $calendarUri);
			$objectData = $vObject->serialize();
			try {
				if ($objectId === null) {
					$objectId = UUIDUtil::getUUID();
					$this->backend->createCalendarObject(
						$calendarId,
						$objectId,
						$objectData
					);
					yield new ImportObjectEvent(
						disposition: ImportDisposition::Created,
						identifier: $uid,
					);
				} else {

View on GitHub (pinned to ecdeb153ff)

Solutions

  1. Read the issue named in the message (it names UID and the first problem) and fix that property in the source data
  2. If invalid entries should be skipped rather than abort the import, use VALIDATE_SKIP and filter the yielded Error events
  3. Only use VALIDATE_NONE when the data is known-good and you accept storing non-conformant objects

Example fix

// before
$options->setValidate(CalendarImportOptions::VALIDATE_FAIL);
$service->import($source, $calendar, $options); // throws on first invalid object

// after
$options->setValidate(CalendarImportOptions::VALIDATE_FAIL);
try {
    foreach ($service->import($source, $calendar, $options) as $event) {}
} catch (\InvalidArgumentException $e) {
    // 'Error importing calendar data: UID <x> - ...' -> fix that object, re-import
}
Defensive patterns

Strategy: validation

Validate before calling

$v = \Sabre\VObject\Reader::read($ics);
$issues = [];
foreach ($v->getBaseComponents() as $c) {
    foreach ($c->validate() as $issue) {
        $issues[] = $issue['message'];
    }
}
// fix $issues before calling import() with VALIDATE_FAIL

Try / catch

try {
    foreach ($service->import($source, $calendar, $options) as $event) {}
} catch (\InvalidArgumentException $e) {
    // contains 'UID <x> - <first issue>'; repair that object and re-import
}

Prevention

When it happens

Trigger: Setting $options->setValidate(CalendarImportOptions::VALIDATE_FAIL) and importing an object that fails \Sabre\VObject\Component::validate(), such as an event missing DTSTART or containing a malformed property.

Common situations: Strict import pipelines that upgrade validation from the default VALIDATE_SKIP; importing third-party exports that are loosely RFC-compliant; schema drift after a sabre/vobject upgrade making previously tolerated data invalid.

Related errors


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