{"record":{"id":"adf6c9a3e334b358","repo":"nextcloud/server","slug":"calendar-calendarid-is-not-writeable","errorCode":null,"errorMessage":"Calendar <$calendarId> is not writeable","messagePattern":"Calendar <\\$calendarId> is not writeable","errorType":"console","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"apps/dav/lib/Command/ImportCalendar.php","lineNumber":92,"sourceCode":"\t\t$showCreated = $input->getOption('show-created');\n\t\t$showUpdated = $input->getOption('show-updated');\n\t\t$showSkipped = $input->getOption('show-skipped');\n\t\t$showErrors = $input->getOption('show-errors');\n\n\t\tif (!$this->userManager->userExists($userId)) {\n\t\t\tthrow new InvalidArgumentException(\"User <$userId> not found.\");\n\t\t}\n\t\t// retrieve calendar and evaluate if import is supported and writeable\n\t\t$calendars = $this->calendarManager->getCalendarsForPrincipal('principals/users/' . $userId, [$calendarId]);\n\t\tif ($calendars === []) {\n\t\t\tthrow new InvalidArgumentException(\"Calendar <$calendarId> not found\");\n\t\t}\n\t\t$calendar = $calendars[0];\n\t\tif (!$calendar instanceof CalendarImpl) {\n\t\t\tthrow new InvalidArgumentException(\"Calendar <$calendarId> doesn't support this function\");\n\t\t}\n\t\tif (!$calendar->isWritable()) {\n\t\t\tthrow new InvalidArgumentException(\"Calendar <$calendarId> is not writeable\");\n\t\t}\n\t\tif ($calendar->isDeleted()) {\n\t\t\tthrow new InvalidArgumentException(\"Calendar <$calendarId> is deleted\");\n\t\t}\n\t\t// construct options object\n\t\t$options = new CalendarImportOptions();\n\t\t$options->setSupersede($supersede);\n\t\tif ($errors !== null) {\n\t\t\t$options->setErrors($errors);\n\t\t}\n\t\tif ($validation !== null) {\n\t\t\t$options->setValidate($validation);\n\t\t}\n\t\t$options->setFormat($format);\n\t\t$options->setCounts(true);\n\t\t// evaluate if a valid location was given and is usable otherwise default to stdin\n\t\tif ($location !== null) {\n\t\t\t$stream = fopen($location, 'r');","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/nextcloud/server/blob/ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3/apps/dav/lib/Command/ImportCalendar.php#L74-L110","documentation":"InvalidArgumentException thrown by occ dav:import-calendar (apps/dav/lib/Command/ImportCalendar.php:92) when CalendarImpl::isWritable() returns false. The import performs direct writes, so the target calendar must be writable - calendars with a read-only owner share or a backend flag preventing writes are rejected.","triggerScenarios":"occ dav:import-calendar alice <uri> ... where the calendar row/share marks it read-only (e.g. shared into the principal with writable=false, or backend permissions deny create).","commonSituations":"Importing into a calendar shared read-only by another user; calendars shared via publish links; permission changes made between discovery and import.","solutions":["Import into a calendar the user owns with write access","Ask the owner to reshare with can-edit, or run the import as the owning user","Verify writability with a test PUT via CalDAV before the bulk import"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"$calendar = $calendars[0];\nif (!$calendar instanceof \\OCA\\DAV\\CalDAV\\CalendarImpl || !$calendar->isWritable()) {\n    throw new RuntimeException('Import target must be writable');\n}","typeGuard":"$isWritableCalendar = fn ($c): bool =>\n    $c instanceof \\OCA\\DAV\\CalDAV\\CalendarImpl && $c->isWritable();","tryCatchPattern":null,"preventionTips":["Run imports as the calendar owner","Reshare read-only calendars with can-edit before importing","Test with a single-event PUT before bulk operations"],"tags":["occ","cli","import","calendar","caldav","read-only","permission-denied"],"backgroundTag":"read-only-resource","analyzedSha":"ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3","analyzedAt":"2026-08-17T01:36:13.386Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}