{"record":{"id":"3e7ecc087283f49f","repo":"siyuan-note/siyuan","slug":"carddav-address-not-found","errorCode":null,"errorMessage":"CardDAV: address not found","messagePattern":"CardDAV: address not found","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/carddav.go","lineNumber":96,"sourceCode":"\t\tName:                 CardDavDefaultAddressBookName,\n\t\tDescription:          \"Default address book\",\n\t\tMaxResourceSize:      addressBookMaxResourceSize,\n\t\tSupportedAddressData: addressBookSupportedAddressData,\n\t}\n\tcontacts = Contacts{\n\t\tloaded:        false,\n\t\tchanged:       false,\n\t\tlock:          sync.Mutex{},\n\t\tbooks:         sync.Map{},\n\t\tbooksMetaData: []*carddav.AddressBook{},\n\t}\n\n\tErrorCardDavPathInvalid = errors.New(\"CardDAV: path is invalid\")\n\n\tErrorCardDavBookNotFound    = errors.New(\"CardDAV: address book not found\")\n\tErrorCardDavBookPathInvalid = errors.New(\"CardDAV: address book path is invalid\")\n\n\tErrorCardDavAddressNotFound                 = errors.New(\"CardDAV: address not found\")\n\tErrorCardDavAddressFileExtensionNameInvalid = errors.New(\"CardDAV: address file extension name is invalid\")\n)\n\n// ImportAddressBook imports an address book from a vCard file (*.vcf)\nfunc ImportAddressBook(addressBookPath, cardContent string) (addresses []*AddressObject, err error) {\n\t// TODO: Check whether the path is valid (PathDepth: Address)\n\t// TODO: Check whether the address book exists\n\t// TODO: Decode the card content\n\t// TODO: Save the cards to the file system\n\treturn\n}\n\n// ExportAddressBook exports an address book to a vCard file (*.vcf)\nfunc ExportAddressBook(addressBookPath string) (cardContent string, err error) {\n\t// TODO: Check whether the path is valid (PathDepth: AddressBook)\n\t// TODO: Check whether the address book exists\n\t// TODO: Encode the card content\n\treturn","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/carddav.go#L78-L114","documentation":"Sentinel error ErrorCardDavAddressNotFound, thrown when a CardDAV GET/PUT/DELETE operation references an address object (vCard) that does not exist under the resolved address book path. It is part of the CardDAV server error set declared in kernel/model/carddav.go and is used by the WebDAV/CardDAV handler stack to map to an HTTP 404. The error is a package-level var, so it is meant to be compared with errors.Is rather than string matching.","triggerScenarios":"A CardDAV client (macOS Contacts, DAVx5, Thunderbird) requests or modifies an address resource by URL whose final path segment does not match any stored .vcf object inside the address book directory. Also produced when an address object was deleted between a PROPFIND and a subsequent GET, or when the path depth check (PathDepth: Address) passes but the file is absent on disk.","commonSituations":"Stale address cache on the client after another device deleted the contact; client guessed a URL instead of using the href returned by PROPFIND; address book folder was partially restored from backup and is missing .vcf files; two clients racing on the same contact.","solutions":["Verify the resource URL matches an href previously returned by a PROPFIND/REPORT on the address book collection.","Re-run an address-book-query REPORT to refresh the client's list of valid hrefs, then retry only against existing resources.","If the object is expected to exist, check the address book directory on disk for the corresponding .vcf file and confirm no sync/history operation removed it.","Handle the 404 gracefully on the client side by dropping the local copy of the deleted contact."],"exampleFix":"// before: client constructs URL by guess\nurl := baseURL + \"/default/\" + guessedID + \".vcf\"\n\n// after: use only hrefs returned by the server\nfor _, href := range propfindResults.Hrefs {\n    get(href) // never fabricate hrefs\n}","handlingStrategy":"validation","validationCode":"// Before issuing a CardDAV GET/PUT/DELETE, confirm the href came from a prior PROPFIND\nfunc isKnownHref(href string, known []string) bool {\n    for _, k := range known {\n        if k == href { return true }\n    }\n    return false\n}","typeGuard":"// Resource paths must end in .vcf and reference a known href\nfunc isValidAddressHref(href string) bool {\n    return strings.HasSuffix(href, \".vcf\")\n}","tryCatchPattern":"if errors.Is(err, model.ErrorCardDavAddressNotFound) { /* refresh hrefs via REPORT, then retry or drop the contact */ }","preventionTips":["Always obtain resource hrefs from a PROPFIND/REPORT response; never construct them by guessing.","Refresh the address list before operating on contacts that may have been deleted elsewhere.","Treat a 404 on an address object as 'contact deleted' and update the local cache accordingly."],"tags":["carddav","contacts","not-found","webdav","validation"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}