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

${filename} is an Invalid Spreadsheet file.

Error message

${filename} is an Invalid Spreadsheet file.

What it means

listWorksheetNames() first calls canRead(), which requires the file to contain both the '<?xml version="1.0"' declaration and the xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" namespace. If either signature substring is missing, the file is treated as not being an Excel 2003 SpreadsheetML file.

Source

Thrown at src/PhpSpreadsheet/Reader/Xml.php:161

            }
        } catch (Throwable $e) {
            throw new Exception($this->xmlFailMessage, 0, $e);
        }
        $this->fileContents = '';

        return $xml;
    }

    /**
     * Reads names of the worksheets from a file, without parsing the whole file to a Spreadsheet object.
     *
     * @return string[]
     */
    public function listWorksheetNames(string $filename): array
    {
        File::assertFile($filename);
        if (!$this->canRead($filename)) {
            throw new Exception($filename . ' is an Invalid Spreadsheet file.');
        }

        $worksheetNames = [];

        $xml = $this->trySimpleXMLLoadStringPrivate($filename);
        if ($xml === false) {
            throw new Exception("Problem reading {$filename}");
        }

        $xml_ss = $xml->children(self::NAMESPACES_SS);
        foreach ($xml_ss->Worksheet as $worksheet) {
            $worksheet_ss = self::getAttributes($worksheet, self::NAMESPACES_SS);
            $worksheetNames[] = (string) $worksheet_ss['Name'];
        }

        return $worksheetNames;
    }

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Use IOFactory::identify($filename) first and dispatch to the matching reader instead of hardcoding Reader\Xml
  2. Call $reader->canRead($filename) yourself and return a friendly 'unsupported format' message when false
  3. If the file is real Excel, convert it to SpreadsheetML/xlsx or use the appropriate reader (Xls/Xlsx)

Example fix

// before
$names = (new \PhpOffice\PhpSpreadsheet\Reader\Xml())->listWorksheetNames('book.xlsx'); // Invalid Spreadsheet file

// after
$type = \PhpOffice\PhpSpreadsheet\IOFactory::identify('book.xlsx');
$names = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($type)->listWorksheetNames('book.xlsx');
Defensive patterns

Strategy: validation

Validate before calling

$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xml();
if (!$reader->canRead($path)) {
    throw new InvalidArgumentException('Not an Excel 2003 SpreadsheetML file');
}
$names = $reader->listWorksheetNames($path);

Type guard

function isSpreadsheetMl(string $path): bool
{
    return (new \PhpOffice\PhpSpreadsheet\Reader\Xml())->canRead($path);
}

Prevention

When it happens

Trigger: Calling listWorksheetNames() with a binary .xls, a zipped .xlsx, plain XML without the Office namespace, or an HTML file saved with an .xml extension.

Common situations: Import pipelines that assume every upload is SpreadsheetML; users renaming files to fake the extension; XML exports from systems that use a different schema.

Related errors


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