{"record":{"id":"4a68dcf863a36ccd","repo":"nextcloud/server","slug":"unknown-property-property","errorCode":null,"errorMessage":"Unknown property: {property}","messagePattern":"Unknown property: (.+?)","errorType":"exception","errorClass":"BadRequest","httpStatus":400,"severity":"error","filePath":"apps/dav/lib/CardDAV/CardDavBackend.php","lineNumber":381,"sourceCode":"\n\t\t$values = [\n\t\t\t'displayname' => null,\n\t\t\t'description' => null,\n\t\t\t'principaluri' => $principalUri,\n\t\t\t'uri' => $url,\n\t\t\t'synctoken' => 1\n\t\t];\n\n\t\tforeach ($properties as $property => $newValue) {\n\t\t\tswitch ($property) {\n\t\t\t\tcase '{DAV:}displayname':\n\t\t\t\t\t$values['displayname'] = $newValue;\n\t\t\t\t\tbreak;\n\t\t\t\tcase '{' . Plugin::NS_CARDDAV . '}addressbook-description':\n\t\t\t\t\t$values['description'] = $newValue;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new BadRequest('Unknown property: ' . $property);\n\t\t\t}\n\t\t}\n\n\t\t// Fallback to make sure the displayname is set. Some clients may refuse\n\t\t// to work with addressbooks not having a displayname.\n\t\tif (is_null($values['displayname'])) {\n\t\t\t$values['displayname'] = $url;\n\t\t}\n\n\t\t[$addressBookId, $addressBookRow] = $this->atomic(function () use ($values) {\n\t\t\t$query = $this->db->getQueryBuilder();\n\t\t\t$query->insert('addressbooks')\n\t\t\t\t->values([\n\t\t\t\t\t'uri' => $query->createParameter('uri'),\n\t\t\t\t\t'displayname' => $query->createParameter('displayname'),\n\t\t\t\t\t'description' => $query->createParameter('description'),\n\t\t\t\t\t'principaluri' => $query->createParameter('principaluri'),\n\t\t\t\t\t'synctoken' => $query->createParameter('synctoken'),","sourceCodeStart":363,"sourceCodeEnd":399,"githubUrl":"https://github.com/nextcloud/server/blob/ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3/apps/dav/lib/CardDAV/CardDavBackend.php#L363-L399","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Create with only {DAV:}displayname (and carddav addressbook-description); apply extra properties afterwards via PROPPATCH","Filter your property list to the accepted set before issuing MKCOL","Parse the property name out of the 400 message to find which client feature emitted it"],"exampleFix":"// before\nMKCOL /addressbooks/users/alice/contacts/\n  set {DAV:}displayname = 'Contacts'\n  set {http://apple.com/ns/ical/}calendar-color = '#0000FF'\n-> 400 Unknown property: {http://apple.com/ns/ical/}calendar-color\n\n// after\nMKCOL /addressbooks/users/alice/contacts/   (displayname only) -> 201\nPROPPATCH /addressbooks/users/alice/contacts/ (calendar-color)  -> 207","handlingStrategy":"validation","validationCode":"const MKCOL_ALLOWED = [\n    '{DAV:}displayname',\n    '{urn:ietf:params:xml:ns:carddav}addressbook-description',\n];\n$createProps = array_intersect_key($props, array_flip(MKCOL_ALLOWED));\n$deferredProps = array_diff_key($props, $createProps); // apply via PROPPATCH after creation","typeGuard":null,"tryCatchPattern":"try {\n    mkcol($uri, $props);\n} catch (\\Sabre\\DAV\\Exception\\BadRequest $e) {\n    if (str_contains($e->getMessage(), 'Unknown property:')) {\n        mkcol($uri, array_intersect_key($props, array_flip(MKCOL_ALLOWED)));\n    }\n}","preventionTips":["Send only displayname and addressbook-description in the MKCOL body","Apply extra properties with PROPPATCH after the collection exists","Parse the offending property name from the 400 message to locate the emitting client feature"],"tags":["carddav","dav","http-400","mkcol","proppatch"],"backgroundTag":"unknown-dav-property","analyzedSha":"ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3","analyzedAt":"2026-08-17T01:36:13.386Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}