{"record":{"id":"7c2c33bb95e5a53b","repo":"nextcloud/server","slug":"creating-collections-in-calendar-objects-is-not-al","errorCode":null,"errorMessage":"Creating collections in calendar objects is not allowed","messagePattern":"Creating collections in calendar objects is not allowed","errorType":"exception","errorClass":"Sabre\\DAV\\Exception\\MethodNotAllowed","httpStatus":405,"severity":"warning","filePath":"apps/dav/lib/CalDAV/Integration/ExternalCalendar.php","lineNumber":76,"sourceCode":"\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;\n\t}\n\n\t/**\n\t * Splits an app-generated calendar-uri into appId and calendarUri\n\t *\n\t * @param string $calendarUri\n\t * @return array\n\t */","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/nextcloud/server/blob/ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3/apps/dav/lib/CalDAV/Integration/ExternalCalendar.php#L58-L94","documentation":"HTTP 405 MethodNotAllowed from the final ExternalCalendar::createDirectory(). Sabre calls createDirectory() when an MKCOL targets a child path under the calendar collection; for app-generated external calendars no child collections can exist, so the request is always rejected.","triggerScenarios":"MKCOL against /remote.php/dav/calendars/<user>/app-generated--<appId>--<uri>/<newpath>/ by a client that creates sub-collections while syncing, or calendar apps that try to create task/sub-calendars under every calendar they see.","commonSituations":"Sync clients that mirror a local folder structure into DAV; calendar apps offering 'create sub-calendar' on all calendars; scripts that MKCOL defensively before writing events.","solutions":["Create regular calendars with MKCOL on the calendar home (/remote.php/dav/calendars/<user>/), not under an app-generated calendar","Skip MKCOL for any calendar whose URI starts with app-generated--","Use occ dav:create-calendar for scripted calendar creation"],"exampleFix":"// before: MKCOL under an external calendar -> 405\nawait mkcol(`/remote.php/dav/calendars/${uid}/app-generated--myapp--team/extra/`);\n// after: create collections only on the calendar home, never inside external calendars\nif (!calUri.startsWith('app-generated--')) {\n  await mkcol(`/remote.php/dav/calendars/${uid}/${newUri}/`);\n}","handlingStrategy":"validation","validationCode":"// client: never MKCOL under an external calendar\nfunction assertMkcolTarget(parentCalUri, child) {\n  if (parentCalUri.startsWith('app-generated--')) {\n    throw new Error('external calendars do not accept sub-collections');\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Create calendars only on the calendar home collection","Skip sync-folder creation for read-only external calendars"],"tags":["caldav","external-calendar","method-not-allowed","mkcol","app-integration"],"backgroundTag":"unsupported-operation","analyzedSha":"ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3","analyzedAt":"2026-08-17T01:36:13.386Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}