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

The resource you tried to create has a reserved name

Error message

The resource you tried to create has a reserved name

What it means

Sabre\DAV\Exception\MethodNotAllowed thrown by UserAddressBooks::createExtendedCollection() (apps/dav/lib/CardDAV/UserAddressBooks.php:117). Names starting with the reserved prefix 'z-app-generated' are set aside for addressbooks provisioned by apps via the CardDAV plugin API (ExternalAddressBook), so MKCOL/MKCOL_EXTENDED with such a name is rejected before the parent creates the collection.

Source

Thrown at apps/dav/lib/CardDAV/UserAddressBooks.php:117

						$this->groupManager
					);
				}

				return new AddressBook($this->carddavBackend, $addressBook, $this->l10n);
			}, $addressBooks);
		}
		/** @var IAddressBook[][] $objectsFromPlugins */
		$objectsFromPlugins = array_map(function (IAddressBookProvider $plugin): array {
			return $plugin->fetchAllForAddressBookHome($this->principalUri);
		}, $this->pluginManager->getAddressBookPlugins());

		return array_merge($objects, ...$objectsFromPlugins);
	}

	#[\Override]
	public function createExtendedCollection($name, MkCol $mkCol) {
		if (ExternalAddressBook::doesViolateReservedName($name)) {
			throw new MethodNotAllowed('The resource you tried to create has a reserved name');
		}

		parent::createExtendedCollection($name, $mkCol);
	}

	/**
	 * Returns a list of ACE's for this node.
	 *
	 * Each ACE has the following properties:
	 *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
	 *     currently the only supported privileges
	 *   * 'principal', a url to the principal who owns the node
	 *   * 'protected' (optional), indicating that this ACE is not allowed to
	 *      be updated.
	 *
	 * @return array
	 */
	#[\Override]

View on GitHub (pinned to ecdeb153ff)

Solutions

  1. Pick any name that does not start with 'z-app-generated' (e.g. 'personal', 'work') for user-created addressbooks
  2. If you are writing an app that provisions addressbooks, register an IAddressBookProvider plugin instead of MKCOL - the reserved namespace is exactly what identifies plugin books
  3. Strip or rename the prefix when importing/migrating data from another instance

Example fix

// before
$client->request('MKCOL', '/remote.php/dav/addressbooks/users/alice/z-app-generated--myapp-1', $body);
// after
$client->request('MKCOL', '/remote.php/dav/addressbooks/users/alice/my-app-book', $body);
Defensive patterns

Strategy: validation

Validate before calling

// reject reserved names client-side before MKCOL
const RESERVED_PREFIX = 'z-app-generated';
if (name.startsWith(RESERVED_PREFIX)) {
    throw new Error(`Addressbook name must not start with ${RESERVED_PREFIX}`);
}

Type guard

const isReservedAddressBookName = (name: string): boolean =>
    name.startsWith('z-app-generated');

Try / catch

try {
    await client.createAddressBook(name);
} catch (e) {
    if (e.status === 405 && /reserved name/.test(e.message)) {
        // pick another name; this namespace belongs to app plugins
    }
}

Prevention

When it happens

Trigger: An MKCOL or extended MKCOL (addressbook creation) request on /remote.php/dav/addressbooks/users/<uid>/ whose display name or URI begins with 'z-app-generated' (e.g. 'z-app-generated--deck-123'). Same rejection applies in CalendarHome for calendars via the analogous ExternalCalendar::doesViolateReservedName().

Common situations: A client that copies an app-generated addressbook URI from one server to another and tries to recreate it; admin import/sync scripts that replay URIs observed via PROPFIND; custom apps that picked a URI prefix colliding with the reserved one.

Related errors


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