{"record":{"id":"b344057dfb7d35b3","repo":"PHPOffice/PhpSpreadsheet","slug":"could-not-find-zip-member-zipfile","errorCode":null,"errorMessage":"Could not find zip member $zipfile","messagePattern":"Could not find zip member \\$zipfile","errorType":"exception","errorClass":"PhpOffice\\PhpSpreadsheet\\Reader\\Exception","httpStatus":null,"severity":"error","filePath":"src/PhpSpreadsheet/Shared/File.php","lineNumber":174,"sourceCode":"    }\n\n    /**\n     * Assert that given path is an existing file and is readable, otherwise throw exception.\n     */\n    public static function assertFile(string $filename, string $zipMember = ''): void\n    {\n        self::prohibitWrappers($filename);\n        if (!is_file($filename) || !is_readable($filename)) {\n            throw new ReaderException('File \"' . $filename . '\" does not exist or is not readable.');\n        }\n\n        if ($zipMember !== '') {\n            $zipfile = \"zip://$filename#$zipMember\";\n            if (!self::fileExists($zipfile)) {\n                // Has the file been saved with Windoze directory separators rather than unix?\n                $zipfile = \"zip://$filename#\" . str_replace('/', '\\\\', $zipMember);\n                if (!self::fileExists($zipfile)) {\n                    throw new ReaderException(\"Could not find zip member $zipfile\");\n                }\n            }\n        }\n    }\n\n    /**\n     * Same as assertFile, except return true/false and don't throw Exception.\n     * Will nevertheless throw if filename uses invalid protocol, e.g. phar.\n     */\n    public static function testFileNoThrow(string $filename, ?string $zipMember = null): bool\n    {\n        self::prohibitWrappers($filename);\n        if (!is_file($filename) || !is_readable($filename)) {\n            return false;\n        }\n        if ($zipMember === null) {\n            return true;\n        }","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/PHPOffice/PhpSpreadsheet/blob/65b080eef4d9fd11a5796135ab145883e5c3d6a6/src/PhpSpreadsheet/Shared/File.php#L156-L192","documentation":"The second stage of File::assertFile() when a $zipMember is supplied (src/PhpSpreadsheet/Shared/File.php:174): it probes zip://$filename#$zipMember, retries with backslashes (workbooks saved by some Windows tools store members with '\\' separators), and throws when both fail. Readers use it to fetch specific archive parts of an .xlsx (e.g. xl/worksheets/sheet1.xml, drawings, sharedStrings referenced by rels).","triggerScenarios":"An .xlsx missing a part its relationships reference (sheet XML, drawing, sharedStrings); members stored with unexpected path casing or nesting; a corrupt zip central directory so member lookup fails despite the file opening.","commonSituations":"Third-party xlsx generators (report SDKs, Java/Python tools) that omit referenced-but-optional parts; partially uploaded files; archives rewritten by tools that changed internal paths; e-mail/AV-mangled files.","solutions":["Open the archive yourself and inspect actual member names: $zip = new ZipArchive(); $zip->open($file); then list entries to spot missing or oddly-cased parts","Re-save the workbook in Excel/LibreOffice to rebuild a normalized archive, or regenerate from the source system","Catch the ReaderException in upload handlers and quarantine the file with a user-friendly message","Validate zip integrity (unzip -t) at the trust boundary before processing"],"exampleFix":"// before\n$spreadsheet = (new \\PhpOffice\\PhpSpreadsheet\\Reader\\Xlsx())->load('report.xlsx'); // throws on missing member\n\n// after\n$zip = new \\ZipArchive();\nif ($zip->open('report.xlsx') !== true\n    || $zip->locateName('xl/worksheets/sheet1.xml') === false) {\n    throw new \\InvalidArgumentException('Workbook is missing required parts.');\n}\n$zip->close();\n$spreadsheet = (new \\PhpOffice\\PhpSpreadsheet\\Reader\\Xlsx())->load('report.xlsx');","handlingStrategy":"validation","validationCode":"function xlsxHasEssentialMembers(string $path): bool\n{\n    $zip = new \\ZipArchive();\n    if ($zip->open($path) !== true) { return false; }\n    $ok = $zip->locateName('[Content_Types].xml') !== false\n        && $zip->locateName('xl/workbook.xml') !== false;\n    $zip->close();\n\n    return $ok;\n}\n\nif (!xlsxHasEssentialMembers($path)) {\n    throw new \\InvalidArgumentException('Incomplete .xlsx archive');\n}","typeGuard":null,"tryCatchPattern":"try {\n    $spreadsheet = $reader->load($path);\n} catch (\\PhpOffice\\PhpSpreadsheet\\Reader\\Exception $e) {\n    if (str_contains($e->getMessage(), 'Could not find zip member')) {\n        quarantine($path, $e->getMessage()); // missing part: repair via re-save or reject\n    }\n}","preventionTips":["unzip -t or ZipArchive integrity checks at the upload boundary","Re-save third-party-generated workbooks with Excel/LibreOffice before processing","Quarantine (not retry) archives with missing referenced parts"],"tags":["zip","xlsx","missing-file","archive","corrupt-file"],"backgroundTag":"missing-archive-entry","analyzedSha":"65b080eef4d9fd11a5796135ab145883e5c3d6a6","analyzedAt":"2026-08-17T05:40:41.646Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}