nextcloud/server · warning · Sabre\DAV\Exception\NotFound

Node not found

Error message

Node not found

What it means

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.

Solutions

  1. Confirm the object still exists in the source app and note its UID and X-FILENAME
  2. App developers: make ICalendar::search() honor X-FILENAME and UID so DAV lookups resolve (see OCP\Calendar\IQueryOptions)
  3. Clients: treat 404 as 'refresh the collection listing' - cached hrefs are stale
Defensive patterns

Strategy: validation

Validate before calling

// The calendar node itself offers the check - use it before GET/PUT
if (!$appCalendar->childExists($name)) {
    // stale href: refetch the collection listing instead of requesting the object
}

Try / catch

try {
    $object = $appCalendar->getChild($name);
} catch (Sabre\DAV\Exception\NotFound $e) {
    // object gone or provider cannot resolve X-FILENAME/UID - refresh listing
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of nextcloud/server@ecdeb153ff (2026-08-17). Data as JSON: /api/errors/7716060482e8752c. Report an issue: GitHub.

Appendix: source

Thrown at apps/dav/lib/CalDAV/AppCalendar/AppCalendar.php:180

			return false;
		}
	}

	#[\Override]
	public function getChild($name) {
		// Try to get calendar by filename
		$children = $this->calendar->search($name, ['X-FILENAME']);
		if (count($children) === 0) {
			// If nothing found try to get by UID from filename
			$pos = strrpos($name, '.ics');
			$children = $this->calendar->search(substr($name, 0, $pos ?: null), ['UID']);
		}

		if (count($children) > 0) {
			return new CalendarObject($this, $this->calendar, new VCalendar($children));
		}

		throw new NotFound('Node not found');
	}

	/**
	 * @return ICalendarObject[]
	 */
	#[\Override]
	public function getChildren(): array {
		$objects = $this->calendar->search('');
		// We need to group by UID (actually by filename but we do not have that information)
		$result = [];
		foreach ($objects as $object) {
			$uid = (string)$object['UID'] ?: uniqid();
			if (!isset($result[$uid])) {
				$result[$uid] = [];
			}
			$result[$uid][] = $object;
		}

View on GitHub (pinned to ecdeb153ff)