{"record":{"id":"4dc0eabf949b9281","repo":"nextcloud/server","slug":"permission-denied-to-delete-the-trashbin","errorCode":null,"errorMessage":"Permission denied to delete the trashbin","messagePattern":"Permission denied to delete the trashbin","errorType":"exception","errorClass":"Forbidden","httpStatus":403,"severity":"error","filePath":"apps/dav/lib/CalDAV/Trashbin/TrashbinHome.php","lineNumber":109,"sourceCode":"\t\t\tnew RestoreTarget(),\n\t\t\tnew DeletedCalendarObjectsCollection(\n\t\t\t\t$this->caldavBackend,\n\t\t\t\t$this->principalInfo\n\t\t\t),\n\t\t];\n\t}\n\n\t#[\\Override]\n\tpublic function childExists($name): bool {\n\t\treturn in_array($name, [\n\t\t\tRestoreTarget::NAME,\n\t\t\tDeletedCalendarObjectsCollection::NAME,\n\t\t], true);\n\t}\n\n\t#[\\Override]\n\tpublic function delete() {\n\t\tthrow new Forbidden('Permission denied to delete the trashbin');\n\t}\n\n\t#[\\Override]\n\tpublic function getName(): string {\n\t\treturn self::NAME;\n\t}\n\n\t#[\\Override]\n\tpublic function setName($name) {\n\t\tthrow new Forbidden('Permission denied to rename the trashbin');\n\t}\n\n\t#[\\Override]\n\tpublic function getLastModified(): int {\n\t\treturn 0;\n\t}\n\n\t#[\\Override]","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/nextcloud/server/blob/ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3/apps/dav/lib/CalDAV/Trashbin/TrashbinHome.php#L91-L127","documentation":"TrashbinHome::delete() throws Sabre\\DAV\\Exception\\Forbidden unconditionally: the CalDAV trashbin collection itself can never be removed via DAV. A DELETE aimed at /remote.php/dav/calendars/<user>/trashbin always yields HTTP 403, even though the owner's ACL grants {DAV:}all on the node - the privilege only covers operations the node actually supports.","triggerScenarios":"DELETE /remote.php/dav/calendars/<user>/trashbin; an 'empty all' client feature that walks every discovered collection including the trashbin; cleanup scripts recursing over the whole DAV tree.","commonSituations":"Users clicking 'delete' on the trashbin node shown in a client's tree view; migration or cleanup tooling that issues DELETE to every collection it finds.","solutions":["Do not DELETE the trashbin root; it is a permanent per-principal system collection","Remove deleted items individually under trashbin/objects/ instead","Filter the trashbin out of any recursive delete/cleanup logic"],"exampleFix":"// before\nDELETE /remote.php/dav/calendars/alice/trashbin\n-> 403 Permission denied to delete the trashbin\n\n// after\nDELETE /remote.php/dav/calendars/alice/trashbin/objects/old-event.ics","handlingStrategy":"validation","validationCode":"if (rtrim($deleteTarget, '/') === \"/remote.php/dav/calendars/{$user}/trashbin\") {\n    return; // never DELETE the trashbin collection itself\n}","typeGuard":null,"tryCatchPattern":"try {\n    $client->request('DELETE', $uri);\n} catch (\\Sabre\\HTTP\\ClientHttpException $e) {\n    if ($e->getResponse()->getStatus() === 403 && str_ends_with(rtrim($uri, '/'), '/trashbin')) {\n        return; // permanent system collection: skip\n    }\n    throw $e;\n}","preventionTips":["Exclude system collections such as the trashbin from recursive cleanup jobs","Offer per-object purge under trashbin/objects/ instead of deleting the root","Log-and-skip 403s from immutable collections rather than surfacing them as failures"],"tags":["caldav","dav","trashbin","http-403","delete"],"backgroundTag":"dav-403-forbidden","analyzedSha":"ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3","analyzedAt":"2026-08-17T01:36:13.386Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}