{"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":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/carddav.go","lineNumber":97,"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":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/carddav.go#L79-L115","documentation":"Sentinel error ErrorCardDavAddressFileExtensionNameInvalid, thrown when a CardDAV address object resource path does not end with the expected .vcf extension. The CardDAV handler enforces this before any disk read/write to prevent arbitrary file access inside the address book directory. Like the other CardDAV sentinels it is a package-level var meant for errors.Is comparison.","triggerScenarios":"A PUT or GET to an address book path whose final segment uses a non-.vcf extension (e.g. .json, .txt, no extension), or a path containing a query string that confuses extension extraction. Also triggered by malformed client requests that POST to a collection URL with the wrong suffix.","commonSituations":"A custom CardDAV client or integration script writes contacts with the wrong file extension; a migration tool imported contacts as .json; a client appends cache-busting query parameters that become part of the perceived extension.","solutions":["Ensure every address object URL ends with .vcf (lowercase) before issuing PUT/GET requests.","Strip query strings and fragments from the resource path client-side before sending.","If migrating data, convert all address files to valid vCard 3.0/4.0 .vcf files first.","Validate the extension programmatically in the client before contacting the server."],"exampleFix":"// before\npath := fmt.Sprintf(\"/default/%s\", id) // missing extension\n\n// after\nif !strings.HasSuffix(path, \".vcf\") {\n    path += \".vcf\"\n}","handlingStrategy":"validation","validationCode":"// Ensure .vcf extension before any CardDAV address-object request\nfunc ensureVcfExt(p string) string {\n    p = strings.SplitN(p, \"?\", 2)[0]\n    if !strings.HasSuffix(strings.ToLower(p), \".vcf\") {\n        p += \".vcf\"\n    }\n    return p\n}","typeGuard":"func isVcfPath(p string) bool {\n    p = strings.SplitN(p, \"?\", 2)[0]\n    return strings.HasSuffix(strings.ToLower(p), \".vcf\")\n}","tryCatchPattern":"if strings.Contains(err.Error(), \"address file extension name is invalid\") { fixExtensionAndRetry() }","preventionTips":["Standardize all address-object filenames to lowercase .vcf.","Strip query strings from resource paths client-side.","Validate extension programmatically before sending the request."],"tags":["carddav","contacts","validation","file-extension","webdav"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}