PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Reader\Exception

Could not find zip member $zipfile

Error message

Could not find zip member $zipfile

What it means

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).

Source

Thrown at src/PhpSpreadsheet/Shared/File.php:174

    }

    /**
     * Assert that given path is an existing file and is readable, otherwise throw exception.
     */
    public static function assertFile(string $filename, string $zipMember = ''): void
    {
        self::prohibitWrappers($filename);
        if (!is_file($filename) || !is_readable($filename)) {
            throw new ReaderException('File "' . $filename . '" does not exist or is not readable.');
        }

        if ($zipMember !== '') {
            $zipfile = "zip://$filename#$zipMember";
            if (!self::fileExists($zipfile)) {
                // Has the file been saved with Windoze directory separators rather than unix?
                $zipfile = "zip://$filename#" . str_replace('/', '\\', $zipMember);
                if (!self::fileExists($zipfile)) {
                    throw new ReaderException("Could not find zip member $zipfile");
                }
            }
        }
    }

    /**
     * Same as assertFile, except return true/false and don't throw Exception.
     * Will nevertheless throw if filename uses invalid protocol, e.g. phar.
     */
    public static function testFileNoThrow(string $filename, ?string $zipMember = null): bool
    {
        self::prohibitWrappers($filename);
        if (!is_file($filename) || !is_readable($filename)) {
            return false;
        }
        if ($zipMember === null) {
            return true;
        }

View on GitHub (pinned to 65b080eef4)

Solutions

  1. 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
  2. Re-save the workbook in Excel/LibreOffice to rebuild a normalized archive, or regenerate from the source system
  3. Catch the ReaderException in upload handlers and quarantine the file with a user-friendly message
  4. Validate zip integrity (unzip -t) at the trust boundary before processing

Example fix

// before
$spreadsheet = (new \PhpOffice\PhpSpreadsheet\Reader\Xlsx())->load('report.xlsx'); // throws on missing member

// after
$zip = new \ZipArchive();
if ($zip->open('report.xlsx') !== true
    || $zip->locateName('xl/worksheets/sheet1.xml') === false) {
    throw new \InvalidArgumentException('Workbook is missing required parts.');
}
$zip->close();
$spreadsheet = (new \PhpOffice\PhpSpreadsheet\Reader\Xlsx())->load('report.xlsx');
Defensive patterns

Strategy: validation

Validate before calling

function xlsxHasEssentialMembers(string $path): bool
{
    $zip = new \ZipArchive();
    if ($zip->open($path) !== true) { return false; }
    $ok = $zip->locateName('[Content_Types].xml') !== false
        && $zip->locateName('xl/workbook.xml') !== false;
    $zip->close();

    return $ok;
}

if (!xlsxHasEssentialMembers($path)) {
    throw new \InvalidArgumentException('Incomplete .xlsx archive');
}

Try / catch

try {
    $spreadsheet = $reader->load($path);
} catch (\PhpOffice\PhpSpreadsheet\Reader\Exception $e) {
    if (str_contains($e->getMessage(), 'Could not find zip member')) {
        quarantine($path, $e->getMessage()); // missing part: repair via re-save or reject
    }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17). Data as JSON: /api/errors/b344057dfb7d35b3. Report an issue: GitHub.