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

Problem reading {$filename}

Error message

Problem reading {$filename}

What it means

In listWorksheetInfo(), canRead() succeeded but trySimpleXMLLoadStringPrivate() returned false: the bytes contain both signature substrings yet are not well-formed XML, so simplexml refuses the document.

Source

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

    }

    /**
     * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns).
     *
     * @return array<int, array{worksheetName: string, lastColumnLetter: string, lastColumnIndex: int, totalRows: int, totalColumns: int, sheetState: string}>
     */
    public function listWorksheetInfo(string $filename): array
    {
        File::assertFile($filename);
        if (!$this->canRead($filename)) {
            throw new Exception($filename . ' is an Invalid Spreadsheet file.');
        }

        $worksheetInfo = [];

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

        $worksheetID = 1;
        $xml_ss = $xml->children(self::NAMESPACES_SS);
        foreach ($xml_ss->Worksheet as $worksheet) {
            $worksheet_ss = self::getAttributes($worksheet, self::NAMESPACES_SS);

            $tmpInfo = [];
            $tmpInfo['worksheetName'] = '';
            $tmpInfo['lastColumnLetter'] = 'A';
            $tmpInfo['lastColumnIndex'] = 0;
            $tmpInfo['totalRows'] = 0;
            $tmpInfo['totalColumns'] = 0;

            $tmpInfo['worksheetName'] = "Worksheet_{$worksheetID}";
            if (isset($worksheet_ss['Name'])) {
                $tmpInfo['worksheetName'] = (string) $worksheet_ss['Name'];
            }

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Validate with xmllint or a simplexml pre-pass to surface the exact error position
  2. Fix entity escaping (&amp;, &lt;, &gt;) in the generating process
  3. Re-upload or re-export a complete file
Defensive patterns

Strategy: try-catch

Validate before calling

libxml_use_internal_errors(true);
if (simplexml_load_file($path) === false) {
    $err = libxml_get_errors()[0] ?? null;
    throw new InvalidArgumentException('Bad XML: ' . ($err ? $err->message . ' line ' . $err->line : 'unknown'));
}

Try / catch

try {
    $info = $reader->listWorksheetInfo($path);
} catch (\PhpOffice\PhpSpreadsheet\Reader\Exception $e) {
    if (str_contains($e->getMessage(), 'Problem reading')) {
        // malformed despite passing signature: request corrected export
    }
}

Prevention

When it happens

Trigger: Malformed SpreadsheetML: unescaped special characters, mismatched tags, truncation after the header, or scanner-modified content that no longer parses.

Common situations: Hand-built XML exports with escaping bugs; files cut off mid-transfer; XML containing raw ampersands in URLs or unescaped < in text nodes.

Related errors


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