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

Invalid actor "$actorType"

Error message

Invalid actor "$actorType"

What it means

Thrown by the Nextcloud DAV comments plugin when a comment-creating POST carries an actorType other than 'users', or when no user is present in the session. Over DAV only human users may author comments: the actorId is always taken from the authenticated session (userSession->getUser()->getUID()), never from the payload, so any state that leaves $actorId null is rejected. It surfaces as Sabre\DAV\Exception\BadRequest, HTTP 400.

Source

Thrown at apps/dav/lib/Comments/CommentsPlugin.php:220

	 * @throws UnsupportedMediaType if the content type is not supported
	 */
	private function createComment($objectType, $objectId, $data, $contentType = 'application/json') {
		if (explode(';', $contentType)[0] === 'application/json') {
			$data = json_decode($data, true, 512, JSON_THROW_ON_ERROR);
		} else {
			throw new UnsupportedMediaType();
		}

		$actorType = $data['actorType'];
		$actorId = null;
		if ($actorType === 'users') {
			$user = $this->userSession->getUser();
			if (!is_null($user)) {
				$actorId = $user->getUID();
			}
		}
		if (is_null($actorId)) {
			throw new BadRequest('Invalid actor "' . $actorType . '"');
		}

		try {
			$comment = $this->commentsManager->create($actorType, $actorId, $objectType, $objectId);
			$comment->setMessage($data['message']);
			$comment->setVerb($data['verb']);
			$this->commentsManager->save($comment);
			return $comment;
		} catch (\InvalidArgumentException $e) {
			throw new BadRequest('Invalid input values', 0, $e);
		} catch (MessageTooLongException $e) {
			$msg = 'Message exceeds allowed character limit of ';
			throw new BadRequest($msg . IComment::MAX_MESSAGE_LENGTH, 0, $e);
		}
	}
}

View on GitHub (pinned to ecdeb153ff)

Solutions

  1. Set "actorType": "users" in the JSON body — DAV comments accept no other actor type.
  2. Ensure the request carries valid credentials (app password via Basic, or an authenticated browser session) so the user session is populated.
  3. If a non-user actor is required (guest, bot), create the comment server-side via OCP\Comments\ICommentManager::create() instead of the DAV endpoint.

Example fix

// before: HTTP 400 Invalid actor "guests"
$payload = ['actorType' => 'guests', 'objectType' => 'files', 'objectId' => '123', 'verb' => 'comment', 'message' => 'hi'];
$client->request('POST', '/remote.php/dav/comments/files/123/', json_encode($payload));

// after: actorType 'users'; the actorId comes from the authenticated session
$payload = ['actorType' => 'users', 'objectType' => 'files', 'objectId' => '123', 'verb' => 'comment', 'message' => 'hi'];
$client->request('POST', '/remote.php/dav/comments/files/123/', json_encode($payload));
Defensive patterns

Strategy: validation

Validate before calling

if ($currentUser === null) {
    throw new RuntimeException('DAV comment creation requires an authenticated user');
}
if (($payload['actorType'] ?? '') !== 'users') {
    throw new InvalidArgumentException('DAV comments only accept actorType users');
}
$client->request('POST', $commentsUrl, json_encode($payload));

Try / catch

try {
    $client->request('POST', $commentsUrl, $body);
} catch (ClientHttpException $e) {
    if ($e->getResponse()->getStatusCode() === 400
        && str_contains($e->getResponse()->getBody()->getContents(), 'Invalid actor')) {
        // wrong actorType in payload — fix the client, do not retry
    }
}

Prevention

When it happens

Trigger: POST to /remote.php/dav/comments/<objectType>/<objectId> whose JSON body has actorType not exactly 'users' (e.g. 'guests', 'bots'); or the request carries no valid authentication so userSession->getUser() returns null and $actorId stays null even though actorType is 'users'.

Common situations: Clients ported from other comment APIs that send their own actor model; cron jobs or test scripts posting comments without an Authorization header; app code trying to comment as a guest or system actor through the DAV endpoint instead of the server-side ICommentManager.

Related errors


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