{"record":{"id":"4c2187a43d11f399","repo":"siyuan-note/siyuan","slug":"caldav-calendar-object-not-found","errorCode":null,"errorMessage":"CalDAV: calendar object not found","messagePattern":"CalDAV: calendar object not found","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/caldav.go","lineNumber":84,"sourceCode":"\tdefaultCalendar = caldav.Calendar{\n\t\tPath:                  CalDavDefaultCalendarPath,\n\t\tName:                  CalDavDefaultCalendarName,\n\t\tDescription:           \"Default calendar\",\n\t\tMaxResourceSize:       calendarMaxResourceSize,\n\t\tSupportedComponentSet: calendarSupportedComponentSet,\n\t}\n\tcalendars = Calendars{\n\t\tloaded:            false,\n\t\tchanged:           false,\n\t\tlock:              sync.Mutex{},\n\t\tcalendars:         sync.Map{},\n\t\tcalendarsMetaData: []*caldav.Calendar{},\n\t}\n\n\tErrorCalDavCalendarNotFound    = errors.New(\"CalDAV: calendar not found\")\n\tErrorCalDavCalendarPathInvalid = errors.New(\"CalDAV: calendar path is invalid\")\n\n\tErrorCalDavCalendarObjectNotFound    = errors.New(\"CalDAV: calendar object not found\")\n\tErrorCalDavCalendarObjectPathInvalid = errors.New(\"CalDAV: calendar object path is invalid\")\n)\n\n// CalendarsMetaDataFilePath returns the absolute path of the calendars' meta data file\nfunc CalendarsMetaDataFilePath() string {\n\treturn DavPath2DirectoryPath(CalDavCalendarsMetaDataFilePath)\n}\n\nfunc GetCalDavPathDepth(urlPath string) CalDavPathDepth {\n\turlPath = PathCleanWithSlash(urlPath)\n\treturn CalDavPathDepth(len(strings.Split(urlPath, \"/\")) - 1)\n}\n\n// GetCardDavPathDepth parses\nfunc ParseCalendarObjectPath(objectPath string) (calendarPath string, objectID string, err error) {\n\tcalendarPath, objectFileName := path.Split(objectPath)\n\tcalendarPath = PathCleanWithSlash(calendarPath)\n\tobjectID = path.Base(objectFileName)","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/caldav.go#L66-L102","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: blindly updating a cached event\ncal, obj, err := calendars.GetObject(\"/caldav/principals/main/calendars/default/evt-1.ics\")\n\n// after: handle not-found as a 404 and fall back to re-listing objects\ncal, obj, err := calendars.GetObject(objectPath)\nif errors.Is(err, model.ErrorCalDavCalendarObjectNotFound) {\n    objects, lerr := calendar.ListObjects() // refresh known IDs first\n    if lerr != nil { return lerr }\n    if len(objects) == 0 { return err } // object genuinely gone\n}","handlingStrategy":"try-catch","validationCode":"objectPath := \"/caldav/principals/main/calendars/default/evt-1.ics\"\nif model.GetCalDavPathDepth(objectPath) != 6 || !strings.HasSuffix(objectPath, \".ics\") {\n    return fmt.Errorf(\"malformed calendar object path %s\", objectPath)\n}","typeGuard":"func isCalendarObjectPath(p string) bool {\n    return model.GetCalDavPathDepth(p) == 6 && strings.HasSuffix(p, \".ics\")\n}","tryCatchPattern":"if _, obj, err := calendars.GetObject(objectPath); err != nil {\n    if errors.Is(err, model.ErrorCalDavCalendarObjectNotFound) {\n        return http.StatusNotFound // object gone; re-sync instead of failing hard\n    }\n    return err\n}","preventionTips":["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."],"tags":["caldav","calendar","not-found","webdav"],"backgroundTag":"resource-not-found","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}