{"record":{"id":"6c4fa33cf4dd72a2","repo":"nextcloud/server","slug":"creating-a-new-entry-is-not-allowed","errorCode":null,"errorMessage":"Creating a new entry is not allowed","messagePattern":"Creating a new entry is not allowed","errorType":"exception","errorClass":"Sabre\\DAV\\Exception\\Forbidden","httpStatus":403,"severity":"error","filePath":"apps/dav/lib/CalDAV/AppCalendar/AppCalendar.php","lineNumber":116,"sourceCode":"\t\treturn null;\n\t}\n\n\t#[\\Override]\n\tpublic function delete(): void {\n\t\t// No method for deleting a calendar in OCP\\Calendar\\ICalendar\n\t\tthrow new Forbidden('Deleting an entry is not implemented');\n\t}\n\n\t#[\\Override]\n\tpublic function createFile($name, $data = null) {\n\t\tif ($this->calendar instanceof ICreateFromString) {\n\t\t\tif (is_resource($data)) {\n\t\t\t\t$data = stream_get_contents($data) ?: null;\n\t\t\t}\n\t\t\t$this->calendar->createFromString($name, is_null($data) ? '' : $data);\n\t\t\treturn null;\n\t\t} else {\n\t\t\tthrow new Forbidden('Creating a new entry is not allowed');\n\t\t}\n\t}\n\n\t#[\\Override]\n\tpublic function getProperties($properties) {\n\t\treturn [\n\t\t\t'{DAV:}displayname' => $this->calendar->getDisplayName() ?: $this->calendar->getKey(),\n\t\t\t'{http://apple.com/ns/ical/}calendar-color' => $this->calendar->getDisplayColor() ?: '#0082c9',\n\t\t\t'{' . Plugin::NS_CALDAV . '}supported-calendar-component-set' => new SupportedCalendarComponentSet(['VEVENT', 'VJOURNAL', 'VTODO']),\n\t\t];\n\t}\n\n\t#[\\Override]\n\tpublic function calendarQuery(array $filters) {\n\t\t$result = [];\n\t\t$objects = $this->getChildren();\n\n\t\tforeach ($objects as $object) {","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/nextcloud/server/blob/ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3/apps/dav/lib/CalDAV/AppCalendar/AppCalendar.php#L98-L134","documentation":"Creating a new object inside an app calendar collection calls AppCalendar::createFile(); it only succeeds when the backing ICalendar provider also implements OCP\\Calendar\\ICreateFromString. If it does not (read-only provider), the write is refused with Forbidden (HTTP 403) 'Creating a new entry is not allowed'.","triggerScenarios":"PUT/POST creating a new .ics object in an app-registered calendar whose provider class implements only ICalendar (read-only), e.g. a holiday or feed calendar.","commonSituations":"Sync clients attempting two-way sync against read-only app calendars; app authors who forgot that write support requires implementing ICreateFromString (AppCalendar::getPermissions() then also drops to PERMISSION_READ).","solutions":["Verify the calendar provider class implements OCP\\Calendar\\ICreateFromString; without it every write path is 403 by design","App developers: implement createFromString() on the provider to enable CalDAV writes","Clients: check the calendar's permissions/ACL before syncing changes; skip writes when PERMISSION_CREATE is absent"],"exampleFix":"// before\nclass MyCalendarProvider implements ICalendar { /* read-only over CalDAV */ }\n\n// after\nclass MyCalendarProvider implements ICalendar, ICreateFromString {\n    public function createFromString(string $name, ?string $data = null): void { /* persist */ }\n}","handlingStrategy":"type-guard","validationCode":"// App-side: only promise CalDAV writes when the provider supports them\n$calendar = \\OC::$server->get(\\OCP\\Calendar\\IManager::class)->getCalendars()[0];\n$writable = $calendar instanceof \\OCP\\Calendar\\ICreateFromString\n    && ($calendar->getPermissions() & \\OCP\\Constants::PERMISSION_CREATE) !== 0;","typeGuard":"function acceptsCalDavWrites(\\OCP\\Calendar\\ICalendar $c): bool {\n    return $c instanceof \\OCP\\Calendar\\ICreateFromString\n        && ($c->getPermissions() & \\OCP\\Constants::PERMISSION_CREATE) !== 0;\n}","tryCatchPattern":"try {\n    $node->createFile($name, $data);\n} catch (Sabre\\DAV\\Exception\\Forbidden $e) {\n    // read-only app calendar; fall back to read-only sync mode\n}","preventionTips":["Implement ICreateFromString on providers meant to be writable","Clients: inspect calendar permissions/ACL before scheduling writes","Treat 403 on create as a capability flag and stop two-way sync for this calendar"],"tags":["php","webdav","caldav","nextcloud","app-calendar","readonly"],"backgroundTag":"read-only-calendar","analyzedSha":"ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3","analyzedAt":"2026-08-17T01:36:13.386Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}