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
- Use IOFactory::identify($filename) first and dispatch to the matching reader instead of hardcoding Reader\Xml
- Call $reader->canRead($filename) yourself and return a friendly 'unsupported format' message when false
- 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
- Dispatch on IOFactory::identify() rather than assuming the XML format
- Gate upload handling with canRead() to fail with a clear message
- Accept .xlsx by default; treat SpreadsheetML as a legacy convenience
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
- $filename is an Invalid Spreadsheet file.
- Cannot load invalid XML ${fileOrString}: ${filename}
- Unsupported binary comparison operator
- Cloning the calculation engine is not allowed!
- Unsupported numeric binary operation
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/1c82b94ba94323d9.
Report an issue: GitHub.