siyuan-note/siyuan · error

CardDAV: address not found

Error message

CardDAV: address not found

What it means

CardDAV: address not found is a sentinel error (kernel/model/carddav.go:98) returned by GetAddress and DeleteAddress when the requested vCard address object is not present in the address book store. The lookup resolves the address path against an in-memory/cache map; if the key is absent (nil value or wrong type), this error is returned at carddav.go:282 and carddav.go:306. It signals the address (card) does not exist, not that the book is malformed.

Solutions

  1. Verify the address path/href exists by listing the address book contents (e.g. via the CardDAV PROPFIND/report or the imported addresses from ImportAddressBook) before calling GetAddress/DeleteAddress
  2. Re-import the address book with ImportAddressBook if the data directory was restored or the card file was deleted
  3. Check the path spelling and depth: the card file must be a *.vcf inside a valid address book path (otherwise different errors like ErrorCardDavAddressFileExtensionNameInvalid fire)
  4. Handle the sentinel with errors.Is(ErrorCardDavAddressNotFound) and treat it as HTTP 404 toward the CardDAV client rather than a 500

Example fix

// before
typeAssertion := store[key].(*AddressObject)

// after
value, ok := store[key]
if !ok {
    return ErrCardDavAddressNotFound // sentinel; map to 404
}
addressObject, ok := value.(*AddressObject)
if !ok {
    return ErrCardDavAddressNotFound
}
Defensive patterns

Strategy: validation

Validate before calling

// Go
if !addressBookContains(book, addressID) { // list/check before fetch
    return ErrCardDavAddressNotFound
}

Type guard

value, ok := store[key].(*AddressObject)
if !ok { return ErrCardDavAddressNotFound }

Prevention

When it happens

Trigger: Calling GetAddress or DeleteAddress with a path whose address object was never imported, was deleted, or whose key was evicted from the address book map. Also occurs if the stored value's type assertion to *AddressObject fails (map miss in the else branch).

Common situations: Client cached a CardDAV href that was removed on another device or by another sync run; requesting a card before ImportAddressBook populated the book; a stale ETag/URL after the workspace data directory was replaced or restored from backup.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at kernel/model/carddav.go:98

		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
	// TODO: Encode the card content
	return

View on GitHub (pinned to 9f775e8a12)