{"record":{"id":"a9c2e1248a0bedc6","repo":"nextcloud/server","slug":"invalid-actor-actortype","errorCode":null,"errorMessage":"Invalid actor \"$actorType\"","messagePattern":"Invalid actor \"\\$actorType\"","errorType":"http","errorClass":"Sabre\\DAV\\Exception\\BadRequest","httpStatus":400,"severity":"error","filePath":"apps/dav/lib/Comments/CommentsPlugin.php","lineNumber":220,"sourceCode":"\t * @throws UnsupportedMediaType if the content type is not supported\n\t */\n\tprivate function createComment($objectType, $objectId, $data, $contentType = 'application/json') {\n\t\tif (explode(';', $contentType)[0] === 'application/json') {\n\t\t\t$data = json_decode($data, true, 512, JSON_THROW_ON_ERROR);\n\t\t} else {\n\t\t\tthrow new UnsupportedMediaType();\n\t\t}\n\n\t\t$actorType = $data['actorType'];\n\t\t$actorId = null;\n\t\tif ($actorType === 'users') {\n\t\t\t$user = $this->userSession->getUser();\n\t\t\tif (!is_null($user)) {\n\t\t\t\t$actorId = $user->getUID();\n\t\t\t}\n\t\t}\n\t\tif (is_null($actorId)) {\n\t\t\tthrow new BadRequest('Invalid actor \"' . $actorType . '\"');\n\t\t}\n\n\t\ttry {\n\t\t\t$comment = $this->commentsManager->create($actorType, $actorId, $objectType, $objectId);\n\t\t\t$comment->setMessage($data['message']);\n\t\t\t$comment->setVerb($data['verb']);\n\t\t\t$this->commentsManager->save($comment);\n\t\t\treturn $comment;\n\t\t} catch (\\InvalidArgumentException $e) {\n\t\t\tthrow new BadRequest('Invalid input values', 0, $e);\n\t\t} catch (MessageTooLongException $e) {\n\t\t\t$msg = 'Message exceeds allowed character limit of ';\n\t\t\tthrow new BadRequest($msg . IComment::MAX_MESSAGE_LENGTH, 0, $e);\n\t\t}\n\t}\n}\n","sourceCodeStart":202,"sourceCodeEnd":237,"githubUrl":"https://github.com/nextcloud/server/blob/ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3/apps/dav/lib/Comments/CommentsPlugin.php#L202-L237","documentation":"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.","triggerScenarios":"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'.","commonSituations":"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.","solutions":["Set \"actorType\": \"users\" in the JSON body — DAV comments accept no other actor type.","Ensure the request carries valid credentials (app password via Basic, or an authenticated browser session) so the user session is populated.","If a non-user actor is required (guest, bot), create the comment server-side via OCP\\Comments\\ICommentManager::create() instead of the DAV endpoint."],"exampleFix":"// before: HTTP 400 Invalid actor \"guests\"\n$payload = ['actorType' => 'guests', 'objectType' => 'files', 'objectId' => '123', 'verb' => 'comment', 'message' => 'hi'];\n$client->request('POST', '/remote.php/dav/comments/files/123/', json_encode($payload));\n\n// after: actorType 'users'; the actorId comes from the authenticated session\n$payload = ['actorType' => 'users', 'objectType' => 'files', 'objectId' => '123', 'verb' => 'comment', 'message' => 'hi'];\n$client->request('POST', '/remote.php/dav/comments/files/123/', json_encode($payload));","handlingStrategy":"validation","validationCode":"if ($currentUser === null) {\n    throw new RuntimeException('DAV comment creation requires an authenticated user');\n}\nif (($payload['actorType'] ?? '') !== 'users') {\n    throw new InvalidArgumentException('DAV comments only accept actorType users');\n}\n$client->request('POST', $commentsUrl, json_encode($payload));","typeGuard":null,"tryCatchPattern":"try {\n    $client->request('POST', $commentsUrl, $body);\n} catch (ClientHttpException $e) {\n    if ($e->getResponse()->getStatusCode() === 400\n        && str_contains($e->getResponse()->getBody()->getContents(), 'Invalid actor')) {\n        // wrong actorType in payload — fix the client, do not retry\n    }\n}","preventionTips":["Hard-code actorType to 'users' for every DAV comment creation.","Authenticate before posting; the endpoint never allows anonymous authors.","Reserve non-user actors for server-side ICommentManager integration."],"tags":["dav","comments","webdav","sabre","bad-request"],"backgroundTag":"invalid-actor-type","analyzedSha":"ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3","analyzedAt":"2026-08-17T01:36:13.386Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}