{"record":{"id":"d086b9f39ca1542d","repo":"siyuan-note/siyuan","slug":"carddav-address-file-extension-name-is-invalid","errorCode":null,"errorMessage":"CardDAV: address file extension name is invalid","messagePattern":"CardDAV: address file extension name is invalid","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/carddav.go","lineNumber":99,"sourceCode":"\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\n}","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/carddav.go#L81-L117","documentation":"CardDAV: address file extension name is invalid is declared at kernel/model/carddav.go:99 and returned by ParseAddressPath when the final path segment does not carry the required vCard extension (VCardFileExt, i.e. .vcf). CardDAV address objects are stored one-per-file as vCards, so any other extension is rejected before the path is resolved. The check runs at carddav.go:141 after the extension is extracted from the parsed path.","triggerScenarios":"Parsing or requesting an address object path whose file component lacks .vcf — e.g. a PUT/GET/DELETE to a CardDAV URL ending in .json, .txt, or no extension; constructing address paths programmatically without appending VCardFileExt.","commonSituations":"Hand-written CardDAV client URLs; migration tools that copy contacts as generic files; code that builds resource paths from a card UID but forgets the extension; webdav clients normalizing extensions to lowercase/uppercase mismatch if the constant check is case-sensitive.","solutions":["Append the vCard extension to the resource name: build paths as <bookPath>/<uid>.vcf (use the VCardFileExt constant, not a literal)","Validate the filename extension before issuing the request; reject non-.vcf names client-side","If the data was imported with the wrong extension, rename the card files to *.vcf and re-import via ImportAddressBook","Map this sentinel to HTTP 400/404 in the CardDAV handler instead of surfacing it as an internal error"],"exampleFix":"// before\npath := addressBookPath + \"/\" + uid\n\n// after\npath := addressBookPath + \"/\" + uid + VCardFileExt // \"card.vcf\"","handlingStrategy":"validation","validationCode":"if filepath.Ext(name) != VCardFileExt {\n    return fmt.Errorf(\"address %q must end in .vcf\", name)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Build card paths with the VCardFileExt constant instead of string literals","Validate filenames at import time so bad extensions never enter the store"],"tags":["carddav","file-extension","validation"],"backgroundTag":"invalid-argument-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"}