{"record":{"id":"7716060482e8752c","repo":"nextcloud/server","slug":"node-not-found","errorCode":null,"errorMessage":"Node not found","messagePattern":"Node not found","errorType":"exception","errorClass":"Sabre\\DAV\\Exception\\NotFound","httpStatus":404,"severity":"warning","filePath":"apps/dav/lib/CalDAV/AppCalendar/AppCalendar.php","lineNumber":180,"sourceCode":"\t\t\treturn false;\n\t\t}\n\t}\n\n\t#[\\Override]\n\tpublic function getChild($name) {\n\t\t// Try to get calendar by filename\n\t\t$children = $this->calendar->search($name, ['X-FILENAME']);\n\t\tif (count($children) === 0) {\n\t\t\t// If nothing found try to get by UID from filename\n\t\t\t$pos = strrpos($name, '.ics');\n\t\t\t$children = $this->calendar->search(substr($name, 0, $pos ?: null), ['UID']);\n\t\t}\n\n\t\tif (count($children) > 0) {\n\t\t\treturn new CalendarObject($this, $this->calendar, new VCalendar($children));\n\t\t}\n\n\t\tthrow new NotFound('Node not found');\n\t}\n\n\t/**\n\t * @return ICalendarObject[]\n\t */\n\t#[\\Override]\n\tpublic function getChildren(): array {\n\t\t$objects = $this->calendar->search('');\n\t\t// We need to group by UID (actually by filename but we do not have that information)\n\t\t$result = [];\n\t\tforeach ($objects as $object) {\n\t\t\t$uid = (string)$object['UID'] ?: uniqid();\n\t\t\tif (!isset($result[$uid])) {\n\t\t\t\t$result[$uid] = [];\n\t\t\t}\n\t\t\t$result[$uid][] = $object;\n\t\t}\n","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/nextcloud/server/blob/ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3/apps/dav/lib/CalDAV/AppCalendar/AppCalendar.php#L162-L198","documentation":"AppCalendar::getChild() resolves a child by searching the app backend twice: first by X-FILENAME equal to the requested name, then by UID equal to the name minus '.ics'. Zero hits on both searches throws Sabre\\DAV\\Exception\\NotFound (HTTP 404) - the object does not exist in this app calendar, or the app's search() cannot find it under either key.","triggerScenarios":"GET/PROPFIND/PUT on calendars/<user>/<app-calendar>/<name>.ics where <name> matches no X-FILENAME and its '.ics'-stripped form matches no UID in the app backend's search index.","commonSituations":"Client caches referencing objects deleted or renamed in the source app; providers whose search() ignores X-FILENAME or UID filters and always returns nothing; mismatch between the filename a client uses and the app's stored X-FILENAME.","solutions":["Confirm the object still exists in the source app and note its UID and X-FILENAME","App developers: make ICalendar::search() honor X-FILENAME and UID so DAV lookups resolve (see OCP\\Calendar\\IQueryOptions)","Clients: treat 404 as 'refresh the collection listing' - cached hrefs are stale"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// The calendar node itself offers the check - use it before GET/PUT\nif (!$appCalendar->childExists($name)) {\n    // stale href: refetch the collection listing instead of requesting the object\n}","typeGuard":null,"tryCatchPattern":"try {\n    $object = $appCalendar->getChild($name);\n} catch (Sabre\\DAV\\Exception\\NotFound $e) {\n    // object gone or provider cannot resolve X-FILENAME/UID - refresh listing\n}","preventionTips":["App providers: implement search() honoring X-FILENAME and UID filters","Clients: handle 404 by invalidating cached hrefs for that collection","Verify the UID you use matches the object's stored UID when X-FILENAME is absent"],"tags":["php","webdav","caldav","nextcloud","app-calendar","not-found","http-404"],"backgroundTag":"calendar-object-not-found","analyzedSha":"ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3","analyzedAt":"2026-08-17T01:36:13.386Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}