siyuan-note/siyuan · error

CardDAV: address book path is invalid

Error message

CardDAV: address book path is invalid

What it means

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.

Solutions

  1. Use address book paths exactly as returned by CardDAV discovery/listing
  2. Validate path depth with GetCardDavPathDepth before calling ParseAddressPath
  3. Correct extra/missing path segments so depth matches an address book

Example fix

// before
ParseAddressPath("/dav/carddav/addressbooks/")
// after
ParseAddressPath("/dav/carddav/addressbooks/mybook/")
Defensive patterns

Strategy: validation

Validate before calling

if GetCardDavPathDepth(path) != cardDavPathDepth_AddressBook {
    return fmt.Errorf("%q is not an address-book-depth path", path)
}

Try / catch

if errors.Is(err, ErrorCardDavBookPathInvalid) {
    // return 400 and log the malformed path for client-side URL template fixing
}

Prevention

When it happens

Trigger: ParseAddressPath called with a path where GetCardDavPathDepth differs from cardDavPathDepth_AddressBook (missing or extra segments).

Common situations: Manually constructed URLs missing the addressbooks segment; passing an address-object (deeper) path where a book path is expected; trailing segment typos.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/63c4da7f460f1141. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/carddav.go:96

	defaultAddressBook = carddav.AddressBook{
		Path:                 CardDavDefaultAddressBookPath,
		Name:                 CardDavDefaultAddressBookName,
		Description:          "Default address book",
		MaxResourceSize:      addressBookMaxResourceSize,
		SupportedAddressData: addressBookSupportedAddressData,
	}
	contacts = Contacts{
		loaded:        false,
		changed:       false,
		lock:          sync.Mutex{},
		books:         sync.Map{},
		booksMetaData: []*carddav.AddressBook{},
	}

	ErrorCardDavPathInvalid = errors.New("CardDAV: path is invalid")

	ErrorCardDavBookNotFound    = errors.New("CardDAV: address book not found")
	ErrorCardDavBookPathInvalid = errors.New("CardDAV: address book path is invalid")

	ErrorCardDavAddressNotFound                 = errors.New("CardDAV: address not found")
	ErrorCardDavAddressFileExtensionNameInvalid = errors.New("CardDAV: address file extension name is invalid")
)

// ImportAddressBook imports an address book from a vCard file (*.vcf)
func ImportAddressBook(addressBookPath, cardContent string) (addresses []*AddressObject, err error) {
	// TODO: Check whether the path is valid (PathDepth: Address)
	// TODO: Check whether the address book exists
	// TODO: Decode the card content
	// TODO: Save the cards to the file system
	return
}

// ExportAddressBook exports an address book to a vCard file (*.vcf)
func ExportAddressBook(addressBookPath string) (cardContent string, err error) {
	// TODO: Check whether the path is valid (PathDepth: AddressBook)
	// TODO: Check whether the address book exists

View on GitHub (pinned to 9f775e8a12)