{"record":{"id":"9af9ec9c074e79a1","repo":"nextcloud/server","slug":"error-importing-calendar-data-one-or-more-objects-9af9ec","errorCode":null,"errorMessage":"Error importing calendar data: One or more objects discovered with multiple base component types","messagePattern":"Error importing calendar data: One or more objects discovered with multiple base component types","errorType":"validation","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"apps/dav/lib/CalDAV/Import/ImportService.php","lineNumber":298,"sourceCode":"\t\t\t\t\tthrow new InvalidArgumentException('Error importing calendar data: ' . $errorMessage);\n\t\t\t\t}\n\t\t\t\tyield new ImportObjectEvent(\n\t\t\t\t\tdisposition: ImportDisposition::Error,\n\t\t\t\t\tidentifier: null,\n\t\t\t\t\terrors: [$errorMessage]\n\t\t\t\t);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// determine if the object has more than one base component type\n\t\t\t// object can have multiple base components with the same uid\n\t\t\t// but we need to make sure they are of the same type\n\t\t\tif (count($components) > 1) {\n\t\t\t\t$type = $components[0]->name;\n\t\t\t\tforeach ($components as $entry) {\n\t\t\t\t\tif ($type !== $entry->name) {\n\t\t\t\t\t\t$errorMessage = 'One or more objects discovered with multiple base component types';\n\t\t\t\t\t\tif ($options->getErrors() === $options::ERROR_FAIL) {\n\t\t\t\t\t\t\tthrow new InvalidArgumentException('Error importing calendar data: ' . $errorMessage);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tyield new ImportObjectEvent(\n\t\t\t\t\t\t\tdisposition: ImportDisposition::Error,\n\t\t\t\t\t\t\tidentifier: null,\n\t\t\t\t\t\t\terrors: [$errorMessage]\n\t\t\t\t\t\t);\n\t\t\t\t\t\tcontinue 2;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// determine if the object has a uid\n\t\t\tif (!isset($components[0]->UID)) {\n\t\t\t\t$errorMessage = 'One or more objects discovered without a UID';\n\t\t\t\tif ($options->getErrors() === $options::ERROR_FAIL) {\n\t\t\t\t\tthrow new InvalidArgumentException('Error importing calendar data: ' . $errorMessage);\n\t\t\t\t}\n\t\t\t\tyield new ImportObjectEvent(\n\t\t\t\t\tdisposition: ImportDisposition::Error,","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/nextcloud/server/blob/ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3/apps/dav/lib/CalDAV/Import/ImportService.php#L280-L316","documentation":"Thrown when an imported calendar object contains more than one base component and they are not all of the same type (for example a VEVENT and a VTODO in one VCALENDAR). CalDAV requires each stored resource to hold components of a single type, so ImportService rejects mixed-type objects when the error mode is ERROR_FAIL. In a non-failing mode it yields an ImportObjectEvent with disposition Error and continues with the next object.","triggerScenarios":"Importing data where one VCALENDAR block groups a recurring event with its VTODO sibling under the same UID (or any VEVENT+VTODO/VJOURNAL mix) while options->getErrors() === CalendarImportOptions::ERROR_FAIL.","commonSituations":"Merging event and task data into one calendar file; exports from tools that bundle related components of different types together; broken object splitting in a custom exporter.","solutions":["Split the offending VCALENDAR block so each object contains only components of one type, keeping the shared UID only within a single type","Run the import with errors below ERROR_FAIL and handle the yielded Error events so the rest of the file still imports","Pre-scan with sabre/vobject: collect getBaseComponents() names and verify they are uniform before importing"],"exampleFix":"// before\n$vObject = \\Sabre\\VObject\\Reader::read($ics);\n// mixed VEVENT+VTODO object -> import() throws\n\n// after\n$vObject = \\Sabre\\VObject\\Reader::read($ics);\n$types = array_unique(array_map(fn ($c) => $c->name, $vObject->getBaseComponents()));\nif (count($types) > 1) {\n    // split per type into separate VCALENDAR objects before import\n}","handlingStrategy":"validation","validationCode":"$v = \\Sabre\\VObject\\Reader::read($ics);\n$names = array_map(fn ($c) => $c->name, $v->getBaseComponents());\nif (count(array_unique($names)) > 1) {\n    // split into one VCALENDAR per component type before importing\n}","typeGuard":"function hasUniformBaseComponents(\\Sabre\\VObject\\Component\\VCalendar $v): bool {\n    $names = array_map(fn ($c) => $c->name, $v->getBaseComponents());\n    return count(array_unique($names)) <= 1;\n}","tryCatchPattern":"try {\n    foreach ($service->import($source, $calendar, $options) as $event) {}\n} catch (\\InvalidArgumentException $e) {\n    // identify the mixed-type object, split it, re-import\n}","preventionTips":["When merging calendars, group components by type as well as UID","Test importers with fixtures containing recurring events plus exceptions (correct) and mixed-type objects (must split)","Keep error mode below ERROR_FAIL during bulk imports"],"tags":["caldav","icalendar","import","nextcloud","php","component-types"],"backgroundTag":"icalendar-import-validation","analyzedSha":"ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3","analyzedAt":"2026-08-17T01:36:13.386Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}