siyuan-note/siyuan · error
CalDAV: calendar object not found
Error message
CalDAV: calendar object not found
What it means
ErrorCalDavCalendarObjectNotFound is a sentinel error thrown by Calendars.GetObject and Calendars.DeleteObject (kernel/model/caldav.go:213,237) when the parent calendar exists but no calendar object (a loaded *.ics event/todo) is registered under the requested object ID in the calendar's in-memory Objects sync.Map. It means the CalDAV client addressed a valid calendar-object URL whose resource has never been PUT, has been DELETEd, or was not loaded from disk at startup. It maps to HTTP 404 in CalDAV semantics.
Source
Thrown at kernel/model/caldav.go:84
defaultCalendar = caldav.Calendar{
Path: CalDavDefaultCalendarPath,
Name: CalDavDefaultCalendarName,
Description: "Default calendar",
MaxResourceSize: calendarMaxResourceSize,
SupportedComponentSet: calendarSupportedComponentSet,
}
calendars = Calendars{
loaded: false,
changed: false,
lock: sync.Mutex{},
calendars: sync.Map{},
calendarsMetaData: []*caldav.Calendar{},
}
ErrorCalDavCalendarNotFound = errors.New("CalDAV: calendar not found")
ErrorCalDavCalendarPathInvalid = errors.New("CalDAV: calendar path is invalid")
ErrorCalDavCalendarObjectNotFound = errors.New("CalDAV: calendar object not found")
ErrorCalDavCalendarObjectPathInvalid = errors.New("CalDAV: calendar object path is invalid")
)
// CalendarsMetaDataFilePath returns the absolute path of the calendars' meta data file
func CalendarsMetaDataFilePath() string {
return DavPath2DirectoryPath(CalDavCalendarsMetaDataFilePath)
}
func GetCalDavPathDepth(urlPath string) CalDavPathDepth {
urlPath = PathCleanWithSlash(urlPath)
return CalDavPathDepth(len(strings.Split(urlPath, "/")) - 1)
}
// GetCardDavPathDepth parses
func ParseCalendarObjectPath(objectPath string) (calendarPath string, objectID string, err error) {
calendarPath, objectFileName := path.Split(objectPath)
calendarPath = PathCleanWithSlash(calendarPath)
objectID = path.Base(objectFileName)View on GitHub (pinned to 8641553a1f)
Solutions
- Re-fetch the calendar object list (REPORT/propfind on the calendar) and use a URL returned by the server instead of a cached one.
- Verify the .ics file still exists on disk under the calendar directory (DavPath2DirectoryPath of the calendar path); restore it or recreate the object with PUT if needed.
- Restart the SiYuan kernel to force Calendars.load() to re-index the calendar directory and clear stale in-memory state.
- Treat the error as HTTP 404 on the client side: re-sync the collection and drop tombstones for the missing object.
Example fix
// before: blindly updating a cached event
cal, obj, err := calendars.GetObject("/caldav/principals/main/calendars/default/evt-1.ics")
// after: handle not-found as a 404 and fall back to re-listing objects
cal, obj, err := calendars.GetObject(objectPath)
if errors.Is(err, model.ErrorCalDavCalendarObjectNotFound) {
objects, lerr := calendar.ListObjects() // refresh known IDs first
if lerr != nil { return lerr }
if len(objects) == 0 { return err } // object genuinely gone
} Defensive patterns
Strategy: try-catch
Validate before calling
objectPath := "/caldav/principals/main/calendars/default/evt-1.ics"
if model.GetCalDavPathDepth(objectPath) != 6 || !strings.HasSuffix(objectPath, ".ics") {
return fmt.Errorf("malformed calendar object path %s", objectPath)
} Type guard
func isCalendarObjectPath(p string) bool {
return model.GetCalDavPathDepth(p) == 6 && strings.HasSuffix(p, ".ics")
} Try / catch
if _, obj, err := calendars.GetObject(objectPath); err != nil {
if errors.Is(err, model.ErrorCalDavCalendarObjectNotFound) {
return http.StatusNotFound // object gone; re-sync instead of failing hard
}
return err
} Prevention
- Always derive object URLs from the server's object listing rather than long-lived client caches.
- Delete objects via the API (DeleteObject) so in-memory indexes and disk stay consistent; never remove .ics files by hand.
- Check errors.Is(err, ErrorCalDavCalendarObjectNotFound) explicitly and map it to HTTP 404 for CalDAV clients.
- After out-of-band file changes, restart the kernel or trigger a reload so the in-memory object index matches disk.
When it happens
Trigger: GetObject(objectPath) or DeleteObject(objectPath) is called with a path like /caldav/principals/main/calendars/default/<id>.ics that parses correctly (calendar path depth is calDavPathDepth_Calendar) but calendar.Objects.Load(objectID) / LoadAndDelete(objectID) misses: the object ID does not exist, was already deleted, or the .ics file was removed from the workspace directory without reloading.
Common situations: A calendar client (Thunderbird, Apple Calendar, DAVx5) references an event deleted on another device or server-side; the .ics file was manually deleted from data/storage or synced out; a client caches an ETag/URL for an object that no longer exists; a stale sync between the client's local store and the kernel's in-memory index.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- CalDAV: calendar object path is invalid
- CardDAV: address book not found
- attribute view not found
- view not found
- key not found
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/4c2187a43d11f399.
Report an issue: GitHub.