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 property attribute

What it means

Thrown while deserializing {http://nextcloud.com/ns}param-filter in a search REPORT: the element must carry a property attribute (the iCal property the parameter belongs to, e.g. PARTSTAT), and ParamFilter::xmlDeserialize() throws Sabre\DAV\Exception\BadRequest (HTTP 400) when $att['property'] is not a string.

Source

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

use Sabre\Xml\XmlDeserializable;

class ParamFilter implements XmlDeserializable {

	/**
	 * @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 property attribute naming the component property that owns the parameter: <n:param-filter property="ATTENDEE" name="PARTSTAT"/>
  2. Keep param-filter nested inside a prop-filter that targets the same property
  3. Validate the filter tree structure before sending the REPORT

Example fix

// before
<n:param-filter name="PARTSTAT"/>

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

Strategy: validation

Validate before calling

function buildParamFilter(string $property, string $name): string {
    foreach (['property' => $property, 'name' => $name] as $v) {
        if ($v === '' || !ctype_upper($v)) {
            throw new InvalidArgumentException('param-filter needs non-empty property and name');
        }
    }
    return "<n:param-filter property=\"{$property}\" name=\"{$name}\"/>";
}

Type guard

function isValidParamFilterAttrs(array $att): bool {
    return isset($att['property'], $att['name'])
        && is_string($att['property']) && $att['property'] !== ''
        && is_string($att['name']) && $att['name'] !== '';
}

Try / catch

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

Prevention

When it happens

Trigger: Sending <n:param-filter name="PARTSTAT"/> without property="ATTENDEE" inside <n:prop-filter>.

Common situations: Confusing param-filter with prop-filter and omitting the property attribute; hand-crafted XML from docs examples that only show the name attribute.

Related errors


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