{"record":{"id":"63c4da7f460f1141","repo":"siyuan-note/siyuan","slug":"carddav-address-book-path-is-invalid","errorCode":null,"errorMessage":"CardDAV: address book path is invalid","messagePattern":"CardDAV: address book path is invalid","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/carddav.go","lineNumber":96,"sourceCode":"\tdefaultAddressBook = carddav.AddressBook{\n\t\tPath:                 CardDavDefaultAddressBookPath,\n\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","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/carddav.go#L78-L114","documentation":"ErrorCardDavBookPathInvalid is returned by ParseAddressPath when the depth of the given address book path does not equal cardDavPathDepth_AddressBook, meaning the path does not have the exact segment layout required to identify an address book.","triggerScenarios":"ParseAddressPath called with a path where GetCardDavPathDepth differs from cardDavPathDepth_AddressBook (missing or extra segments).","commonSituations":"Manually constructed URLs missing the addressbooks segment; passing an address-object (deeper) path where a book path is expected; trailing segment typos.","solutions":["Use address book paths exactly as returned by CardDAV discovery/listing","Validate path depth with GetCardDavPathDepth before calling ParseAddressPath","Correct extra/missing path segments so depth matches an address book"],"exampleFix":"// before\nParseAddressPath(\"/dav/carddav/addressbooks/\")\n// after\nParseAddressPath(\"/dav/carddav/addressbooks/mybook/\")","handlingStrategy":"validation","validationCode":"if GetCardDavPathDepth(path) != cardDavPathDepth_AddressBook {\n    return fmt.Errorf(\"%q is not an address-book-depth path\", path)\n}","typeGuard":null,"tryCatchPattern":"if errors.Is(err, ErrorCardDavBookPathInvalid) {\n    // return 400 and log the malformed path for client-side URL template fixing\n}","preventionTips":["Use the exact book hrefs from CardDAV discovery","Distinguish address-book paths from address-object paths in client code","Centralize CardDAV URL construction to enforce correct depth"],"tags":["carddav","url","validation"],"backgroundTag":"invalid-url-format","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}