{"record":{"id":"828969d21200a97f","repo":"getgrav/grav","slug":"ziparchiver-failed-to-read-entry-name-from-a","errorCode":null,"errorMessage":"ZipArchiver: failed to read entry \"{name}\" from {archive_file}.","messagePattern":"ZipArchiver: failed to read entry \"(.+?)\" from (.+?)\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"system/src/Grav/Common/Filesystem/ZipArchiver.php","lineNumber":261,"sourceCode":"            fclose($stream);\n        }\n    }\n\n    /**\n     * Close the archive, remove everything extracted so far, and throw. Keeps a\n     * rejected archive from leaving partial output on disk.\n     *\n     * @param ZipArchive $zip\n     * @param string $destination\n     * @param string $message\n     * @return never\n     */\n    protected function abortExtraction(ZipArchive $zip, string $destination, string $message): void\n    {\n        $zip->close();\n        Folder::delete($destination);\n\n        throw new RuntimeException($message);\n    }\n\n    /**\n     * @param string $source\n     * @param callable|null $status\n     * @return $this\n     */\n    public function compress($source, ?callable $status = null)\n    {\n        if (!extension_loaded('zip')) {\n            throw new InvalidArgumentException('ZipArchiver: Zip PHP module not installed...');\n        }\n\n        // Get real path for our folder\n        $rootPath = realpath($source);\n        if (!$rootPath) {\n            throw new InvalidArgumentException('ZipArchiver: ' . $source . ' cannot be found...');\n        }","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/getgrav/grav/blob/6040efed04efa69b8209448ed81308e7c24147c2/system/src/Grav/Common/Filesystem/ZipArchiver.php#L243-L279","documentation":"When the size cap is active, ZipArchiver extracts through extractStreamed(), reading each entry with $zip->getStream($name). If getStream returns false for an entry, the archiver calls abortExtraction(): it closes the zip, deletes the partially-extracted destination folder (so nothing half-written remains), and throws RuntimeException 'ZipArchiver: failed to read entry \"<name>\" from <archive>'. A single unreadable entry aborts and rolls back the whole extraction.","triggerScenarios":"A corrupt or mismatched central directory (entry declared but data unreadable); password-encrypted entries — getStream() fails for encrypted zips; CRC errors or truncated entry data from an incomplete download; archive modified while being extracted.","commonSituations":"Partially downloaded GPM packages; password-protected zips uploaded where the workflow expects plain ones; storage-level corruption on uploads; archives created by tools with zip64 quirks that older libzip mishandles per-entry.","solutions":["Test the archive: unzip -t file.zip pinpoints bad entries; re-download or re-create the archive if any fail","If the zip is password-protected, decrypt/re-pack it without a password before feeding it to ZipArchiver (it has no password support)","Check for concurrent modification — do not rebuild the zip while extraction runs","Update the zip extension/libzip on legacy systems to fix per-entry zip64 read failures"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"$zip = new ZipArchive();\nif ($zip->open($path) === true) {\n    for ($i = 0; $i < $zip->count(); $i++) {\n        $stat = $zip->statIndex($i);\n        if (($stat['encryption_method'] ?? 0) !== 0) {\n            $zip->close();\n            throw new RuntimeException('Encrypted entries are not supported: ' . $stat['name']);\n        }\n    }\n    $zip->close();\n}","typeGuard":null,"tryCatchPattern":"try {\n    (new ZipArchiver($path))->extract($destination);\n} catch (RuntimeException $e) {\n    if (str_contains($e->getMessage(), 'failed to read entry')) {\n        // destination was auto-rolled back; unzip -t to find the bad entry, re-download/re-pack, retry\n    }\n}","preventionTips":["Run unzip -t on incoming archives — per-entry corruption shows up there first","Do not feed password-protected zips into this path; it has no password support","Note that failure here is all-or-nothing: the destination folder is deleted on abort, so retry from a clean state"],"tags":["grav","zip","corrupt-archive","stream-read","rollback","encrypted-zip"],"backgroundTag":"zip-entry-read-failed","analyzedSha":"6040efed04efa69b8209448ed81308e7c24147c2","analyzedAt":"2026-08-17T05:07:31.593Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}