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
- Pick any name that does not start with 'z-app-generated' (e.g. 'personal', 'work') for user-created addressbooks
- 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
- 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
- Namespace app provisioned data behind the plugin API, not MKCOL
- Validate user-chosen URIs against the reserved prefix client-side
- On migration, rewrite any z-app-generated URIs before recreating them
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
- URI too long. Address book not created
- Unknown property: {property}
- Too many addressbooks created
- AddressBook limit reached
- Creating collections in address book objects is not allowed
AI-assisted analysis of nextcloud/server@ecdeb153ff (2026-08-17).
Data as JSON: /api/errors/e529cbb8c97fd8c7.
Report an issue: GitHub.