{"record":{"id":"7a4fc9527cb3d507","repo":"nextcloud/server","slug":"requested-file-can-currently-not-be-accessed","errorCode":null,"errorMessage":"Requested file can currently not be accessed.","messagePattern":"Requested file can currently not be accessed\\.","errorType":"exception","errorClass":"Sabre\\DAV\\Exception\\ServiceUnavailable","httpStatus":503,"severity":"error","filePath":"apps/dav/lib/Connector/Sabre/ZipFolderPlugin.php","lineNumber":85,"sourceCode":"\t\t$this->server->on('method:GET', $this->handleDownload(...), 100);\n\t\t// low priority to give any other afterMethod:* a chance to fire before we cancel everything\n\t\t$this->server->on('afterMethod:GET', $this->afterDownload(...), 999);\n\t}\n\n\t/**\n\t * Adding a node to the archive streamer.\n\t * This will recursively add new nodes to the stream if the node is a directory.\n\t */\n\tprotected function streamNode(Streamer $streamer, NcNode $node, string $rootPath): void {\n\t\t// Remove the root path from the filename to make it relative to the requested folder\n\t\t$filename = str_replace($rootPath, '', $node->getPath());\n\n\t\t$mtime = $node->getMTime();\n\t\tif ($node instanceof NcFile) {\n\t\t\t$resource = $node->fopen('rb');\n\t\t\tif ($resource === false) {\n\t\t\t\t$this->logger->info('Cannot read file for zip stream', ['filePath' => $node->getPath()]);\n\t\t\t\tthrow new \\Sabre\\DAV\\Exception\\ServiceUnavailable('Requested file can currently not be accessed.');\n\t\t\t}\n\t\t\t$streamer->addFileFromStream($resource, $filename, $node->getSize(), $mtime);\n\t\t} elseif ($node instanceof NcFolder) {\n\t\t\t$streamer->addEmptyDir($filename, $mtime);\n\t\t\t$content = $node->getDirectoryListing();\n\t\t\tforeach ($content as $subNode) {\n\t\t\t\t$this->streamNode($streamer, $subNode, $rootPath);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Download a folder as an archive.\n\t * It is possible to filter / limit the files that should be downloaded,\n\t * either by passing (multiple) `X-NC-Files: the-file` headers\n\t * or by setting a `files=JSON_ARRAY_OF_FILES` URL query.\n\t */\n\tpublic function handleDownload(Request $request, Response $response): ?false {","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/nextcloud/server/blob/ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3/apps/dav/lib/Connector/Sabre/ZipFolderPlugin.php#L67-L103","documentation":"ZipFolderPlugin::streamNode() (apps/dav/lib/Connector/Sabre/ZipFolderPlugin.php:85) throws ServiceUnavailable (HTTP 503) when $node->fopen('rb') returns false while building the streamed ZIP of a folder download (GET on a collection with zip streaming enabled). The node was listed and passed permission checks, but opening it for reading failed — so the archive cannot be completed and the stream is aborted mid-download.","triggerScenarios":"Downloading a folder as ZIP (GET /remote.php/dav/files/user/folder or the zip-download route) where at least one contained file cannot be opened: underlying file unreadable on the storage, permissions changed since listing, external storage glitch, or the file removed between listing and streaming.","commonSituations":"Folder downloads containing a file on a flaky external mount; a file whose read is denied by ACL/group-folder rules applied at open time; antivirus or ransomware-protection locking files during the zip; very large folders where state changes mid-stream.","solutions":["Retry the folder download — if a file was transiently locked/unreadable, a second attempt often succeeds.","Identify the unreadable file: the server log line 'Cannot read file for zip stream' with filePath pinpoints it; then open that single file directly (GET) to see its specific error.","Fix or remove the offending file (restore permissions, repair the mount, delete a corrupt entry), then re-download the folder.","As a workaround, download files individually or exclude the broken subtree from the ZIP request."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// before zipping, verify each file is readable\nforeach ($folder->getDirectoryListing() as $node) {\n    if ($node instanceof \\OCP\\Files\\File && !$node->isReadable()) {\n        $this->logger->warning('Skipping unreadable file in zip', ['path' => $node->getPath()]);\n        continue;\n    }\n    $this->streamNode($streamer, $node, $rootPath);\n}","typeGuard":null,"tryCatchPattern":"try {\n    $this->streamNode($streamer, $node, $rootPath);\n} catch (\\Sabre\\DAV\\Exception\\ServiceUnavailable $e) {\n    $this->logger->warning('Skipping unreadable file in folder zip', ['filePath' => $node->getPath()]);\n    // fallback: skip the single file and finish the archive rather than aborting the whole download\n}","preventionTips":["Check isReadable() on nodes before adding them to a streamed archive.","Log the failing filePath (as the plugin does) so users can repair it quickly.","Retry folder downloads once before assuming corruption; mid-stream failures are often transient."],"tags":["dav","zip-download","folder-download","file-read","service-unavailable"],"backgroundTag":"file-read-failed","analyzedSha":"ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3","analyzedAt":"2026-08-17T01:36:13.386Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}