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

  1. Re-fetch the calendar object list (REPORT/propfind on the calendar) and use a URL returned by the server instead of a cached one.
  2. 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.
  3. Restart the SiYuan kernel to force Calendars.load() to re-index the calendar directory and clear stale in-memory state.
  4. 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

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


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/4c2187a43d11f399. Report an issue: GitHub.