nextcloud/server · error · Sabre\DAV\Exception\Forbidden
Creating a new entry is not allowed
Error message
Creating a new entry is not allowed
What it means
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'.
Source
Thrown at apps/dav/lib/CalDAV/AppCalendar/AppCalendar.php:116
return null;
}
#[\Override]
public function delete(): void {
// No method for deleting a calendar in OCP\Calendar\ICalendar
throw new Forbidden('Deleting an entry is not implemented');
}
#[\Override]
public function createFile($name, $data = null) {
if ($this->calendar instanceof ICreateFromString) {
if (is_resource($data)) {
$data = stream_get_contents($data) ?: null;
}
$this->calendar->createFromString($name, is_null($data) ? '' : $data);
return null;
} else {
throw new Forbidden('Creating a new entry is not allowed');
}
}
#[\Override]
public function getProperties($properties) {
return [
'{DAV:}displayname' => $this->calendar->getDisplayName() ?: $this->calendar->getKey(),
'{http://apple.com/ns/ical/}calendar-color' => $this->calendar->getDisplayColor() ?: '#0082c9',
'{' . Plugin::NS_CALDAV . '}supported-calendar-component-set' => new SupportedCalendarComponentSet(['VEVENT', 'VJOURNAL', 'VTODO']),
];
}
#[\Override]
public function calendarQuery(array $filters) {
$result = [];
$objects = $this->getChildren();
foreach ($objects as $object) {View on GitHub (pinned to ecdeb153ff)
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
Example fix
// before
class MyCalendarProvider implements ICalendar { /* read-only over CalDAV */ }
// after
class MyCalendarProvider implements ICalendar, ICreateFromString {
public function createFromString(string $name, ?string $data = null): void { /* persist */ }
} Defensive patterns
Strategy: type-guard
Validate before calling
// App-side: only promise CalDAV writes when the provider supports them
$calendar = \OC::$server->get(\OCP\Calendar\IManager::class)->getCalendars()[0];
$writable = $calendar instanceof \OCP\Calendar\ICreateFromString
&& ($calendar->getPermissions() & \OCP\Constants::PERMISSION_CREATE) !== 0; Type guard
function acceptsCalDavWrites(\OCP\Calendar\ICalendar $c): bool {
return $c instanceof \OCP\Calendar\ICreateFromString
&& ($c->getPermissions() & \OCP\Constants::PERMISSION_CREATE) !== 0;
} Try / catch
try {
$node->createFile($name, $data);
} catch (Sabre\DAV\Exception\Forbidden $e) {
// read-only app calendar; fall back to read-only sync mode
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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).
Related errors
- This calendar-object is read-only
- Setting ACL is not supported on this node
- Deleting an entry is not implemented
- Node not found
- Setting ACL is not supported on this node
AI-assisted analysis of nextcloud/server@ecdeb153ff (2026-08-17).
Data as JSON: /api/errors/6c4fa33cf4dd72a2.
Report an issue: GitHub.