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

Unable to read data from {$pFilename}

Error message

Unable to read data from {$pFilename}

What it means

The Ods reader opens the file as a ZipArchive and parses its meta.xml entry with simplexml. When that entry is missing, empty, or unparseable, it throws 'Unable to read data from {$pFilename}'. Upstream bug worth knowing: the message is single-quoted, so it literally prints {$pFilename} and never shows the actual filename (the code variable is even named $filename).

Source

Thrown at src/PhpSpreadsheet/Reader/Ods.php:325

    /**
     * Loads PhpSpreadsheet from file into PhpSpreadsheet instance.
     */
    public function loadIntoExisting(string $filename, Spreadsheet $spreadsheet): Spreadsheet
    {
        File::assertFile($filename, self::INITIAL_FILE);

        $zip = new ZipArchive();
        $zip->open($filename);

        // Meta

        $xml = @simplexml_load_string(
            $this->getSecurityScannerOrThrow()
                ->scan($zip->getFromName('meta.xml'))
        );
        if ($xml === false) {
            throw new Exception('Unable to read data from {$pFilename}');
        }

        /** @var array{meta?: string, office?: string, dc?: string} */
        $namespacesMeta = $xml->getNamespaces(true);

        (new DocumentProperties($spreadsheet))->load($xml, $namespacesMeta);

        // Styles

        $this->allStyles = $this->numberFormats = [];
        $dom = new DOMDocument('1.01', 'UTF-8');
        $dom->loadXML(
            $this->getSecurityScannerOrThrow()
                ->scan($zip->getFromName('styles.xml'))
        );
        $officeNs = (string) $dom->lookupNamespaceUri('office');
        $styleNs = (string) $dom->lookupNamespaceUri('style');
        $fontNs = (string) $dom->lookupNamespaceUri('fo');

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Re-save the file in LibreOffice or Excel so a complete, valid ODS (including meta.xml) is regenerated
  2. Verify the archive contents (unzip -l file.ods should list meta.xml); if absent, rebuild the zip with a minimal meta.xml or re-export
  3. Use IOFactory::identify() to confirm the file really is an ODS before blaming the reader

Example fix

# before (shell): file is an ODS lacking meta.xml
$spreadsheet = (new Ods())->load('report.ods'); // throws literal 'Unable to read data from {$pFilename}'

# after: regenerate a complete archive first
soffice --headless --convert-to ods --outdir fixed report.ods
$spreadsheet = (new Ods())->load('fixed/report.ods');
Defensive patterns

Strategy: validation

Validate before calling

$zip = new ZipArchive();
if ($zip->open($filename) !== true || $zip->locateName('meta.xml') === false) {
    throw new RuntimeException('ODS archive missing or lacks meta.xml: ' . $filename);
}
$zip->close();
$spreadsheet = (new Ods())->load($filename);

Prevention

When it happens

Trigger: An .ods whose zip lacks meta.xml (some third-party generators omit it); a corrupt or truncated archive; a non-ODS zip merely renamed .ods; interrupted downloads.

Common situations: Files produced by lightweight Java/Python ODS writers that skip meta.xml; uploads corrupted in transit; archives rebuilt by tools that dropped entries.

Related errors


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