nextcloud/server · error · CalendarException
Could not create new calendar event: {message}
Error message
Could not create new calendar event: {message} What it means
Thrown as OCA\DAV\CalDAV\CalendarException by CalendarImpl::createFromStringInServer() when the embedded sabre/dav server rejects $server->createFile() with a Conflict while writing a new event object. The original sabre Conflict message is appended, so the CalendarException text is a wrapper around the underlying DAV conflict reason. It surfaces through the public ICalendar API methods createFromString() and createFromStringMinimal().
Source
Thrown at apps/dav/lib/CalDAV/CalendarImpl.php:223
throw new CalendarException('Could not write to calendar as URI parameter is missing');
}
// Build full calendar path
[, $user] = uriSplit($this->calendar->getPrincipalURI());
$fullCalendarFilename = sprintf('calendars/%s/%s/%s', $user, $this->calendarInfo['uri'], $name);
// Force calendar change URI
/** @var Schedule\Plugin $schedulingPlugin */
$schedulingPlugin = $server->getPlugin('caldav-schedule');
$schedulingPlugin->setPathOfCalendarObjectChange($fullCalendarFilename);
$stream = fopen('php://memory', 'rb+');
fwrite($stream, $calendarData);
rewind($stream);
try {
$server->createFile($fullCalendarFilename, $stream);
} catch (Conflict $e) {
throw new CalendarException('Could not create new calendar event: ' . $e->getMessage(), 0, $e);
} finally {
fclose($stream);
}
}
#[\Override]
public function createFromString(string $name, string $calendarData): void {
$server = new EmbeddedCalDavServer(false);
$this->createFromStringInServer($name, $calendarData, $server->getServer());
}
#[\Override]
public function createFromStringMinimal(string $name, string $calendarData): void {
$server = new InvitationResponseServer(false);
$this->createFromStringInServer($name, $calendarData, $server->getServer());
}
/**View on GitHub (pinned to ecdeb153ff)
Solutions
- Generate a unique object name per event (e.g. the event UID plus a random suffix) before calling createFromString().
- Before creating, check whether an object with that name already exists (calendarQuery/search on the ICalendar or the CalDAV backend) and update instead of create.
- Catch CalendarException around createFromString(), inspect the chained Conflict via getPrevious(), and decide skip/update/rename on collision.
- For imports, track which UIDs were already written so re-runs are idempotent.
Example fix
// before
$calendar->createFromString('event.ics', $calendarData);
// after
$name = $eventUid . '-' . bin2hex(random_bytes(4)) . '.ics';
try {
$calendar->createFromString($name, $calendarData);
} catch (CalendarException $e) {
// object name collision or scheduling conflict; inspect $e->getPrevious()
$logger->warning('Event create failed: ' . $e->getMessage());
} Defensive patterns
Strategy: try-catch
Validate before calling
// derive a collision-free name before creating
$objectName = $eventUid . '.ics';
$existing = $calendar->search('', ['UID'], ['uid' => $eventUid]); // or calendarQuery via backend
if ($existing !== []) {
$objectName = $eventUid . '-' . bin2hex(random_bytes(4)) . '.ics';
} Try / catch
try {
$calendar->createFromString($name, $calendarData);
} catch (\OCA\DAV\CalDAV\CalendarException $e) {
if ($e->getPrevious() instanceof \Sabre\DAV\Exception\Conflict) {
// name collision or scheduling conflict -> rename and retry once, or update existing
}
throw $e;
} Prevention
- Always derive object filenames from a unique UID instead of constants like 'event.ics'.
- Make import scripts idempotent by recording written UIDs.
- Log the chained Conflict message (getPrevious()) to distinguish collision from other createFile conflicts.
When it happens
Trigger: Calling $calendar->createFromString($name, $calendarData) (or createFromStringMinimal) on an OCA\DAV\CalDAV\CalendarImpl when an object with the same filename already exists under calendars/<user>/<calendarUri>/<name>, or when the CalDAV scheduling/plugin layer reports a conflict during the PUT into the embedded server. Typical from calendar import scripts that reuse a fixed object name or re-run after a partial failure.
Common situations: Bulk iCalendar imports that derive the object name from a UID and hit the same UID twice; retrying an import after a timeout without skipping already-created events; concurrent requests creating the same event name; testing event creation in a loop with a hardcoded '.ics' filename.
Related errors
- Calendar is a subscription, not writable, shared or deleted
- Calendar does not support VEVENT components
- Parameters missing in order to complete the request. Missing
- Parameters missing in order to complete the request. Missing
- Parameters missing in order to complete the request. Missing
AI-assisted analysis of nextcloud/server@ecdeb153ff (2026-08-17).
Data as JSON: /api/errors/805807daf4d0d604.
Report an issue: GitHub.