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

Renaming address books is not yet supported

Error message

Renaming address books is not yet supported

What it means

HTTP 405 MethodNotAllowed from the final ExternalAddressBook::setName(), which always throws. ExternalAddressBook is the CardDAV counterpart of ExternalCalendar: apps extend it to expose app-backed address books with URIs prefixed app-generated--<appId>--. Sabre calls setName() on MOVE, so renaming an app-registered address book is rejected by design.

Source

Thrown at apps/dav/lib/CardDAV/Integration/ExternalAddressBook.php:59

	/**
	 * @inheritDoc
	 */
	#[\Override]
	final public function getName() {
		return implode(self::DELIMITER, [
			self::PREFIX,
			$this->appId,
			$this->uri,
		]);
	}

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

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

	/**
	 * Checks whether the address book uri is app-generated
	 *
	 * @param string $uri
	 *
	 * @return bool
	 */
	public static function isAppGeneratedAddressBook(string $uri): bool {

View on GitHub (pinned to ecdeb153ff)

Solutions

  1. Rename or reconfigure the address book inside the app that provides it
  2. Do not issue DAV MOVE on address books whose URI starts with app-generated--
  3. If you are the provider app, change the exposed uri and let clients re-discover

Example fix

// before: MOVE an app-generated address book -> 405
await davMove(`/remote.php/dav/addressbooks/${uid}/${bookUri}/`, `/remote.php/dav/addressbooks/${uid}/${newUri}/`);
// after: skip app-generated address books when renaming
if (bookUri.startsWith('app-generated--')) { continue; }
await davMove(`/remote.php/dav/addressbooks/${uid}/${bookUri}/`, `/remote.php/dav/addressbooks/${uid}/${newUri}/`);
Defensive patterns

Strategy: validation

Validate before calling

// client: filter rename targets
function isRenamableAddressBook(bookUri) {
  return !bookUri.startsWith('app-generated--');
}

Type guard

// PHP (server-side)
function isRenamable(\Sabre\DAV\INode $node): bool {
  if ($node instanceof \OCA\DAV\CardDAV\Integration\ExternalAddressBook) {
    return false;
  }
  return !str_starts_with($node->getName(), 'app-generated--');
}

Try / catch

try {
  await davMove(src, dst);
} catch (e) {
  if (e.status === 405) { /* renaming unsupported: manage via provider app */ }
  else throw e;
}

Prevention

When it happens

Trigger: A CardDAV client issuing MOVE on /remote.php/dav/addressbooks/<user>/app-generated--<appId>--<uri>/ — rename attempts from contact clients or sync tools that rename every writable-looking collection.

Common situations: Users renaming address books contributed by apps (e.g. app-provided contact backends); automation that normalizes collection names during migration.

Related errors


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