{"record":{"id":"603f683f48864094","repo":"siyuan-note/siyuan","slug":"caldav-calendar-object-path-is-invalid","errorCode":null,"errorMessage":"CalDAV: calendar object path is invalid","messagePattern":"CalDAV: calendar object path is invalid","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/caldav.go","lineNumber":85,"sourceCode":"\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)\n\tobjectFileExt := util.Ext(objectFileName)","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/caldav.go#L67-L103","documentation":"ErrorCalDavCalendarObjectPathInvalid is returned by ParseCalendarObjectPath (kernel/model/caldav.go:110-113) when the file name portion of a calendar object URL does not end with the iCalendar extension '.ics'. The calendar path depth check passed, so the URL targets a calendar, but the last segment is not a well-formed object file name. GetObject/DeleteObject propagate it after path parsing fails.","triggerScenarios":"ParseCalendarObjectPath is given a path whose final segment lacks the .ics extension (e.g. /caldav/principals/main/calendars/default/evt-1, .../evt-1.ical, or .../calendars.json), typically via Calendars.GetObject, Calendars.DeleteObject, or a CalDAV request handler routing an object URL.","commonSituations":"A client PUTs or requests an object without appending .ics (some hand-rolled CalDAV scripts do this); a plugin or integration builds the object URL by concatenation and forgets the extension; a directory listing URL is mistakenly treated as an object URL.","solutions":["Append the .ics extension to the object file name in the URL before calling the API (ICalendarFileExt = \".ics\").","If the server generates the path, verify it returns URLs ending in .ics as declared by the calendar's resource list.","Check path building code for dropped extensions (e.g. using path.Base of an ID instead of id + \".ics\").","Confirm the URL depth matches /caldav/principals/main/calendars/<calendar>/<object>.ics (6 segments)."],"exampleFix":"// before\nobjectPath := calPath + \"/\" + eventID\nobj, err := ParseCalendarObjectPath(objectPath) // ErrorCalDavCalendarObjectPathInvalid\n\n// after\nobjectPath := calPath + \"/\" + eventID + \".ics\"\nobj, err := ParseCalendarObjectPath(objectPath)","handlingStrategy":"validation","validationCode":"if !strings.HasSuffix(objectPath, \".ics\") {\n    return fmt.Errorf(\"calendar object path must end with .ics: %s\", objectPath)\n}\nif _, _, err := model.ParseCalendarObjectPath(objectPath); err != nil {\n    return err\n}","typeGuard":"func hasICalendarExt(objectPath string) bool {\n    return path.Ext(objectPath) == \".ics\"\n}","tryCatchPattern":"if _, _, err := model.ParseCalendarObjectPath(p); err != nil {\n    if errors.Is(err, model.ErrorCalDavCalendarObjectPathInvalid) {\n        p = strings.TrimSuffix(p, path.Ext(p)) + \".ics\" // normalize once\n    }\n}","preventionTips":["Build object paths with the ICalendarFileExt constant instead of hard-coded or omitted extensions.","Normalize client-supplied object URLs early: append .ics when the final segment has no extension.","Unit-test path builders to assert every generated URL parses via ParseCalendarObjectPath without error.","Keep object IDs extension-free internally and only add .ics when composing the URL."],"tags":["caldav","calendar","path","validation","webdav"],"backgroundTag":"invalid-argument-format","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}