{"record":{"id":"1f781dca20fe293e","repo":"nextcloud/server","slug":"renaming-calendars-is-not-yet-supported","errorCode":null,"errorMessage":"Renaming calendars is not yet supported","messagePattern":"Renaming calendars is not yet supported","errorType":"exception","errorClass":"Sabre\\DAV\\Exception\\MethodNotAllowed","httpStatus":405,"severity":"warning","filePath":"apps/dav/lib/CalDAV/Integration/ExternalCalendar.php","lineNumber":68,"sourceCode":"\n\t/**\n\t * @inheritDoc\n\t */\n\t#[\\Override]\n\tfinal public function getName() {\n\t\treturn implode(self::DELIMITER, [\n\t\t\tself::PREFIX,\n\t\t\t$this->appId,\n\t\t\t$this->calendarUri,\n\t\t]);\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\t#[\\Override]\n\tfinal public function setName($name) {\n\t\tthrow new DAV\\Exception\\MethodNotAllowed('Renaming calendars is not yet supported');\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\t#[\\Override]\n\tfinal public function createDirectory($name) {\n\t\tthrow new DAV\\Exception\\MethodNotAllowed('Creating collections in calendar objects is not allowed');\n\t}\n\n\t/**\n\t * Checks whether the calendar uri is app-generated\n\t *\n\t * @param string $calendarUri\n\t * @return bool\n\t */\n\tpublic static function isAppGeneratedCalendar(string $calendarUri):bool {\n\t\treturn str_starts_with($calendarUri, self::PREFIX) && substr_count($calendarUri, self::DELIMITER) >= 2;","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/nextcloud/server/blob/ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3/apps/dav/lib/CalDAV/Integration/ExternalCalendar.php#L50-L86","documentation":"HTTP 405 MethodNotAllowed thrown from the final ExternalCalendar::setName(), which always throws. ExternalCalendar is the abstract base apps extend to expose app-backed calendars through the CalDAV integration API (ICalendarProvider); its URI always looks like app-generated--<appId>--<calendarUri>. Sabre invokes setName() when a MOVE targets the calendar collection, so renaming any app-registered calendar is rejected by design.","triggerScenarios":"A CalDAV client issuing MOVE on /remote.php/dav/calendars/<user>/app-generated--<appId>--<uri>/ — e.g. drag-and-drop rename in a calendar UI, or a sync client's repair pass that tries to normalize calendar names.","commonSituations":"Users attempting to rename calendars contributed by third-party apps (app store apps that register calendars); automated clients that rename every writable-looking calendar; app updates that changed the exposed calendar URI.","solutions":["Rename or reconfigure the calendar inside the app that provides it (its settings UI or API)","Do not issue DAV MOVE on calendars whose URI starts with app-generated--; filter them out of rename flows","If you are the provider app, expose a different calendarUri and let clients re-discover calendars via PROPFIND"],"exampleFix":"// before: MOVE any calendar, including app-generated ones -> 405\nawait davMove(`/remote.php/dav/calendars/${uid}/${calUri}/`, `/remote.php/dav/calendars/${uid}/${newUri}/`);\n// after: skip app-generated calendars when renaming\nif (calUri.startsWith('app-generated--')) { continue; }\nawait davMove(`/remote.php/dav/calendars/${uid}/${calUri}/`, `/remote.php/dav/calendars/${uid}/${newUri}/`);","handlingStrategy":"validation","validationCode":"// client: filter rename targets\nfunction isRenamableCalendar(calUri) {\n  return !calUri.startsWith('app-generated--');\n}","typeGuard":"// PHP (server-side, when iterating DAV nodes)\nfunction isRenamable(\\Sabre\\DAV\\INode $node): bool {\n  if ($node instanceof \\OCA\\DAV\\CalDAV\\Integration\\ExternalCalendar) {\n    return false;\n  }\n  return !str_starts_with($node->getName(), 'app-generated--');\n}","tryCatchPattern":"try {\n  await davMove(src, dst);\n} catch (e) {\n  if (e.status === 405) { /* rename unsupported for this calendar: surface to user, no retry */ }\n  else throw e;\n}","preventionTips":["Filter app-generated-- URIs out of rename flows","Manage external calendar names in the providing app's settings","Re-discover calendars via PROPFIND after provider apps change URIs"],"tags":["caldav","external-calendar","method-not-allowed","move","app-integration"],"backgroundTag":"unsupported-operation","analyzedSha":"ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3","analyzedAt":"2026-08-17T01:36:13.386Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}