{"record":{"id":"5f145e0cdb5ee047","repo":"PHPOffice/PhpSpreadsheet","slug":"cannot-load-invalid-xml-fileorstring-filenam","errorCode":null,"errorMessage":"Cannot load invalid XML ${fileOrString}: ${filename}","messagePattern":"Cannot load invalid XML (.+?): (.+?)","errorType":"exception","errorClass":"PhpOffice\\PhpSpreadsheet\\Reader\\Exception","httpStatus":null,"severity":"error","filePath":"src/PhpSpreadsheet/Reader/Xml.php","lineNumber":145,"sourceCode":"            $continue = true;\n            if ($data === '' && $fileOrString === 'file') {\n                if ($filename === '') {\n                    $this->xmlFailMessage = 'Cannot load empty path';\n                    $continue = false;\n                } else {\n                    $datax = @file_get_contents($filename);\n                    $data = $datax ?: '';\n                    $continue = $datax !== false;\n                }\n            }\n            if ($continue) {\n                $xml = @simplexml_load_string(\n                    $this->getSecurityScannerOrThrow()\n                        ->scan($data)\n                );\n            }\n        } catch (Throwable $e) {\n            throw new Exception($this->xmlFailMessage, 0, $e);\n        }\n        $this->fileContents = '';\n\n        return $xml;\n    }\n\n    /**\n     * Reads names of the worksheets from a file, without parsing the whole file to a Spreadsheet object.\n     *\n     * @return string[]\n     */\n    public function listWorksheetNames(string $filename): array\n    {\n        File::assertFile($filename);\n        if (!$this->canRead($filename)) {\n            throw new Exception($filename . ' is an Invalid Spreadsheet file.');\n        }\n","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/PHPOffice/PhpSpreadsheet/blob/65b080eef4d9fd11a5796135ab145883e5c3d6a6/src/PhpSpreadsheet/Reader/Xml.php#L127-L163","documentation":"trySimpleXMLLoadStringPrivate() wraps simplexml_load_string plus the security-scanner scan in a try/catch and rethrows with this message, chaining the original Throwable. It fires when the bytes are not well-formed XML, when the XML scanner rejects the content, or on an empty path; the message says whether a 'file' or 'string' was being loaded.","triggerScenarios":"Calling load()/loadIntoExisting() on a file that is not XML at all (binary .xls, zipped .xlsx, HTML), XML with encoding/name errors, or content the Xml reader's security scanner flags (e.g. DTD/XXE patterns); passing an empty filename yields the sibling 'Cannot load empty path' message.","commonSituations":"Using the Excel-2003-XML reader on wrong file types; user uploads renamed to .xml; files with BOM/encoding mismatches; strict security-scanner configuration.","solutions":["Check the previous exception ($e->getPrevious()) — it holds libxml errors or the scanner message and pinpoints the cause","Ensure the file is really SpreadsheetML: it must start with an XML declaration and carry the office:spreadsheet namespace","Pick the right reader via IOFactory::identify()/load() instead of instantiating Reader\\Xml directly","Run xmllint or load the raw string with simplexml yourself to see the exact parse error"],"exampleFix":"// before\n$xmlReader = new \\PhpOffice\\PhpSpreadsheet\\Reader\\Xml();\n$spreadsheet = $xmlReader->load('export.xls'); // Cannot load invalid XML file: export.xls\n\n// after: let IOFactory pick the reader for the actual format\n$spreadsheet = \\PhpOffice\\PhpSpreadsheet\\IOFactory::load('export.xls');","handlingStrategy":"validation","validationCode":"libxml_use_internal_errors(true);\n$raw = file_get_contents($path);\n$probe = simplexml_load_string($raw);\nif ($probe === false) {\n    $first = libxml_get_errors()[0] ?? null;\n    throw new InvalidArgumentException('Malformed XML: ' . ($first ? $first->message : 'unknown'));\n}","typeGuard":null,"tryCatchPattern":"try {\n    $spreadsheet = $reader->load($path);\n} catch (\\PhpOffice\\PhpSpreadsheet\\Reader\\Exception $e) {\n    $cause = $e->getPrevious(); // libxml or security-scanner detail\n    // report $cause?->getMessage() to pinpoint the XML problem\n}","preventionTips":["Use IOFactory::identify() instead of hardcoding Reader\\Xml","Inspect getPrevious() — it carries the real libxml/scanner error","Reject uploads that fail a cheap simplexml well-formedness probe"],"tags":["xml","spreadsheetml","simplexml","reader","phpspreadsheet"],"backgroundTag":"invalid-xml","analyzedSha":"65b080eef4d9fd11a5796135ab145883e5c3d6a6","analyzedAt":"2026-08-17T05:40:41.646Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}