nextcloud/server · warning · Sabre\DAV\Exception\MethodNotAllowed

Creating collections in calendar objects is not allowed

Error message

Creating collections in calendar objects is not allowed

What it means

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.

Source

Thrown at apps/dav/lib/CalDAV/Integration/ExternalCalendar.php:76

			$this->appId,
			$this->calendarUri,
		]);
	}

	/**
	 * @inheritDoc
	 */
	#[\Override]
	final public function setName($name) {
		throw new DAV\Exception\MethodNotAllowed('Renaming calendars is not yet supported');
	}

	/**
	 * @inheritDoc
	 */
	#[\Override]
	final public function createDirectory($name) {
		throw new DAV\Exception\MethodNotAllowed('Creating collections in calendar objects is not allowed');
	}

	/**
	 * Checks whether the calendar uri is app-generated
	 *
	 * @param string $calendarUri
	 * @return bool
	 */
	public static function isAppGeneratedCalendar(string $calendarUri):bool {
		return str_starts_with($calendarUri, self::PREFIX) && substr_count($calendarUri, self::DELIMITER) >= 2;
	}

	/**
	 * Splits an app-generated calendar-uri into appId and calendarUri
	 *
	 * @param string $calendarUri
	 * @return array
	 */

View on GitHub (pinned to ecdeb153ff)

Solutions

  1. Create regular calendars with MKCOL on the calendar home (/remote.php/dav/calendars/<user>/), not under an app-generated calendar
  2. Skip MKCOL for any calendar whose URI starts with app-generated--
  3. Use occ dav:create-calendar for scripted calendar creation

Example fix

// before: MKCOL under an external calendar -> 405
await mkcol(`/remote.php/dav/calendars/${uid}/app-generated--myapp--team/extra/`);
// after: create collections only on the calendar home, never inside external calendars
if (!calUri.startsWith('app-generated--')) {
  await mkcol(`/remote.php/dav/calendars/${uid}/${newUri}/`);
}
Defensive patterns

Strategy: validation

Validate before calling

// client: never MKCOL under an external calendar
function assertMkcolTarget(parentCalUri, child) {
  if (parentCalUri.startsWith('app-generated--')) {
    throw new Error('external calendars do not accept sub-collections');
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of nextcloud/server@ecdeb153ff (2026-08-17). Data as JSON: /api/errors/7c2c33bb95e5a53b. Report an issue: GitHub.