nextcloud/server · error · Sabre\DAV\Exception\BadRequest

The {http://nextcloud.com/ns}param-filter requires a valid p

Error message

The {http://nextcloud.com/ns}param-filter requires a valid parameter attribute

What it means

Second attribute check in ParamFilter::xmlDeserialize(): the {http://nextcloud.com/ns}param-filter element lacks a valid name attribute (the parameter name to match, e.g. PARTSTAT or CN), so $att['name'] is not a string and a Sabre\DAV\Exception\BadRequest (HTTP 400) is thrown for the search REPORT.

Source

Thrown at apps/dav/lib/CalDAV/Search/Xml/Filter/ParamFilter.php:36

	/**
	 * @param Reader $reader
	 * @throws BadRequest
	 * @return string
	 */
	#[\Override]
	public static function xmlDeserialize(Reader $reader) {
		$att = $reader->parseAttributes();
		$property = $att['property'];
		$parameter = $att['name'];

		$reader->parseInnerTree();

		if (!is_string($property)) {
			throw new BadRequest('The {' . SearchPlugin::NS_Nextcloud . '}param-filter requires a valid property attribute');
		}
		if (!is_string($parameter)) {
			throw new BadRequest('The {' . SearchPlugin::NS_Nextcloud . '}param-filter requires a valid parameter attribute');
		}

		return [
			'property' => $property,
			'parameter' => $parameter,
		];
	}
}

View on GitHub (pinned to ecdeb153ff)

Solutions

  1. Add the parameter name: <n:param-filter property="ATTENDEE" name="PARTSTAT"/>
  2. Skip emitting the param-filter element when no parameter name is selected
  3. Assert both attributes are non-empty strings in the code that builds the XML

Example fix

// before
<n:param-filter property="ATTENDEE"/>

// after
<n:param-filter property="ATTENDEE" name="PARTSTAT"/>
Defensive patterns

Strategy: validation

Validate before calling

if (!is_string($paramName) || $paramName === '') {
    // skip the param-filter instead of sending an invalid one
    return '';
}
$xml = "<n:param-filter property=\"{$property}\" name=\"{$paramName}\"/>";

Type guard

function isValidParamName(mixed $name): bool {
    return is_string($name) && $name !== ''
        && preg_match('/^[A-Z0-9-]+$/', $name) === 1;
}

Try / catch

try {
    $client->request('REPORT', $calendarUri, $xmlBody);
} catch (\Sabre\Http\ClientException $e) {
    if ($e->getResponse()?->getStatus() === 400) { /* add name="..." to param-filter */ }
}

Prevention

When it happens

Trigger: Sending <n:param-filter property="ATTENDEE"/> with no name attribute.

Common situations: Client forms that build param filters from optional inputs and skip empty names but still emit the element; typos like param= instead of name=.

Related errors


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