nextcloud/server · error · BadRequest

Unknown property: {property}

Error message

Unknown property: {property}

What it means

During addressbook creation CardDavBackend::createAddressBook() accepts exactly two properties in the MKCOL body: {DAV:}displayname and {urn:ietf:params:xml:ns:carddav}addressbook-description. Every other property falls into the default branch and throws BadRequest('Unknown property: <{ns}name>') (HTTP 400), so the whole MKCOL fails - the offending property name is included verbatim in the message.

Source

Thrown at apps/dav/lib/CardDAV/CardDavBackend.php:381

		$values = [
			'displayname' => null,
			'description' => null,
			'principaluri' => $principalUri,
			'uri' => $url,
			'synctoken' => 1
		];

		foreach ($properties as $property => $newValue) {
			switch ($property) {
				case '{DAV:}displayname':
					$values['displayname'] = $newValue;
					break;
				case '{' . Plugin::NS_CARDDAV . '}addressbook-description':
					$values['description'] = $newValue;
					break;
				default:
					throw new BadRequest('Unknown property: ' . $property);
			}
		}

		// Fallback to make sure the displayname is set. Some clients may refuse
		// to work with addressbooks not having a displayname.
		if (is_null($values['displayname'])) {
			$values['displayname'] = $url;
		}

		[$addressBookId, $addressBookRow] = $this->atomic(function () use ($values) {
			$query = $this->db->getQueryBuilder();
			$query->insert('addressbooks')
				->values([
					'uri' => $query->createParameter('uri'),
					'displayname' => $query->createParameter('displayname'),
					'description' => $query->createParameter('description'),
					'principaluri' => $query->createParameter('principaluri'),
					'synctoken' => $query->createParameter('synctoken'),

View on GitHub (pinned to ecdeb153ff)

Solutions

  1. Create with only {DAV:}displayname (and carddav addressbook-description); apply extra properties afterwards via PROPPATCH
  2. Filter your property list to the accepted set before issuing MKCOL
  3. Parse the property name out of the 400 message to find which client feature emitted it

Example fix

// before
MKCOL /addressbooks/users/alice/contacts/
  set {DAV:}displayname = 'Contacts'
  set {http://apple.com/ns/ical/}calendar-color = '#0000FF'
-> 400 Unknown property: {http://apple.com/ns/ical/}calendar-color

// after
MKCOL /addressbooks/users/alice/contacts/   (displayname only) -> 201
PROPPATCH /addressbooks/users/alice/contacts/ (calendar-color)  -> 207
Defensive patterns

Strategy: validation

Validate before calling

const MKCOL_ALLOWED = [
    '{DAV:}displayname',
    '{urn:ietf:params:xml:ns:carddav}addressbook-description',
];
$createProps = array_intersect_key($props, array_flip(MKCOL_ALLOWED));
$deferredProps = array_diff_key($props, $createProps); // apply via PROPPATCH after creation

Try / catch

try {
    mkcol($uri, $props);
} catch (\Sabre\DAV\Exception\BadRequest $e) {
    if (str_contains($e->getMessage(), 'Unknown property:')) {
        mkcol($uri, array_intersect_key($props, array_flip(MKCOL_ALLOWED)));
    }
}

Prevention

When it happens

Trigger: MKCOL with additional set elements such as {http://apple.com/ns/ical/}calendar-color, {DAV:}sync-token, or app-specific namespaces; a client reusing its calendar-creation payload for addressbooks.

Common situations: Generic DAV clients sending displayname plus color in one MKCOL; clients mixing calendar and addressbook creation code; custom provisioning XML that grew beyond what the server accepts.

Related errors


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