{"record":{"id":"43aabd95924ef5bc","repo":"nextcloud/server","slug":"no-read-permissions-this-might-be-caused-by-files","errorCode":null,"errorMessage":"No read permissions. This might be caused by files_accesscontrol, check your configured rules","messagePattern":"No read permissions\\. This might be caused by files_accesscontrol, check your configured rules","errorType":"exception","errorClass":"OCA\\DAV\\Connector\\Sabre\\Exception\\Forbidden","httpStatus":403,"severity":"error","filePath":"apps/dav/lib/Connector/Sabre/Directory.php","lineNumber":262,"sourceCode":"\n\t/**\n\t * Returns an array with all the child nodes\n\t *\n\t * @return \\Sabre\\DAV\\INode[]\n\t * @throws \\Sabre\\DAV\\Exception\\Locked\n\t * @throws Forbidden\n\t */\n\t#[\\Override]\n\tpublic function getChildren() {\n\t\tif (!is_null($this->dirContent)) {\n\t\t\treturn $this->dirContent;\n\t\t}\n\t\ttry {\n\t\t\tif (!$this->info->isReadable()) {\n\t\t\t\t// return 403 instead of 404 because a 404 would make\n\t\t\t\t// the caller believe that the collection itself does not exist\n\t\t\t\tif (Server::get(IAppManager::class)->isEnabledForAnyone('files_accesscontrol')) {\n\t\t\t\t\tthrow new Forbidden('No read permissions. This might be caused by files_accesscontrol, check your configured rules');\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Forbidden('No read permissions');\n\t\t\t\t}\n\t\t\t}\n\t\t\t$folderContent = $this->getNode()->getDirectoryListing();\n\t\t} catch (LockedException $e) {\n\t\t\tthrow new Locked();\n\t\t}\n\n\t\t$nodes = [];\n\t\t$request = Server::get(IRequest::class);\n\t\t$l10nFactory = Server::get(IFactory::class);\n\t\t$l10n = $l10nFactory->get(Application::APP_ID);\n\t\tforeach ($folderContent as $info) {\n\t\t\t$node = $this->getChild($info->getName(), $info, $request, $l10n);\n\t\t\t$nodes[] = $node;\n\t\t}\n\t\t$this->dirContent = $nodes;","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/nextcloud/server/blob/ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3/apps/dav/lib/Connector/Sabre/Directory.php#L244-L280","documentation":"Directory::getChildren() refuses to list a directory whose underlying storage reports it as non-readable. When the files_accesscontrol app is enabled for anyone, the 403 message appends a hint pointing at workflow rules. Returning 403 instead of 404 is deliberate so callers know the collection itself exists.","triggerScenarios":"PROPFIND (Depth 1) or any listing on a WebDAV directory whose read access is blocked by a files_accesscontrol workflow rule matching the user, path, or file metadata.","commonSituations":"Compliance rules denying groups access to folders; workflow rules with overly broad matchers catching legitimate users; rule changes rolled out without checking affected paths.","solutions":["Ask an admin to review the files_accesscontrol rules matching this path and user (workflow event log shows which rule hit).","Narrow the rule matchers or exclude the affected users, groups, or paths.","If the block is intended, teach clients to render the 403 message instead of retrying."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    $children = $client->propfind($dirUrl, [], 1);\n} catch (Forbidden $e) { // HTTP 403: folder exists but is not listable\n    reportUnreadableFolder($dirUrl, $e->getMessage()); // message names files_accesscontrol\n    // do not retry — a rule must change first\n}","preventionTips":["Map files_accesscontrol rules to affected groups and paths before enabling them.","Surface the 403 message to users — it names the likely cause.","Admins: check the workflow event log to confirm which rule matched."],"tags":["dav","files","files-accesscontrol","workflow","forbidden"],"backgroundTag":"permission-denied","analyzedSha":"ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3","analyzedAt":"2026-08-17T01:36:13.386Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}