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

Problem reading ${filename}

Error message

Problem reading ${filename}

What it means

In listWorksheetNames(), canRead() passed (both signature substrings exist) but simplexml_load_string still returned false, so the document is not parseable XML despite looking like SpreadsheetML at a glance.

Source

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

    }

    /**
     * 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;
    }

    /**
     * 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
    {

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Run xmllint --noout file.xml (or simplexml on the raw bytes) to get the exact parser error and line
  2. Fix or re-export at the source (escape entities, complete the document)
  3. Re-transfer the file if it was truncated in transit

Example fix

// diagnose the underlying parse failure
libxml_use_internal_errors(true);
$doc = simplexml_load_file('upload.xml');
foreach (libxml_get_errors() as $err) {
    error_log($err->message . ' at line ' . $err->line);
}
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 {
    $names = $reader->listWorksheetNames($path);
} catch (\PhpOffice\PhpSpreadsheet\Reader\Exception $e) {
    if (str_contains($e->getMessage(), 'Problem reading')) {
        // file passes signature but is malformed: surface a re-upload request
    }
}

Prevention

When it happens

Trigger: Truncated or malformed XML that retains the declaration and namespace string (e.g. cut mid-element, unescaped ampersand, duplicated attribute), or content the security scanner rewrote/rejected.

Common situations: Partially uploaded files; XML assembled by string concatenation in the producing system; entities like & or < left unescaped in attribute values.

Related errors


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