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

Only Little-Endian encoding is supported.

Error message

Only Little-Endian encoding is supported.

What it means

Thrown by Shared\OLE::read() when the 2-byte field at offset 28 of the compound document is not the expected byte-order marker FE FF. The OLE2 spec defines only little-endian encoding, so a well-formed big-endian file is essentially nonexistent; in practice this exception marks a malformed or damaged header.

Source

Thrown at src/PhpSpreadsheet/Shared/OLE.php:126

     *
     * @return bool true on success, PEAR_Error on failure
     */
    public function read(string $filename): bool
    {
        $fh = @fopen($filename, 'rb');
        if ($fh === false) {
            throw new ReaderException("Can't open file $filename");
        }
        $this->_file_handle = $fh;

        $signature = fread($fh, 8);
        if ("\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1" != $signature) {
            throw new ReaderException("File doesn't seem to be an OLE container.");
        }
        fseek($fh, 28);
        if (fread($fh, 2) != "\xFE\xFF") {
            // This shouldn't be a problem in practice
            throw new ReaderException('Only Little-Endian encoding is supported.');
        }
        // Size of blocks and short blocks in bytes
        /** @var int<1, max> */
        $temp = 2 ** self::readInt2($fh);
        $this->bigBlockSize = $temp;
        $this->smallBlockSize = 2 ** self::readInt2($fh);

        // Skip UID, revision number and version number
        fseek($fh, 44);
        // Number of blocks in Big Block Allocation Table
        $bbatBlockCount = self::readInt4($fh);

        // Root chain 1st block
        $directoryFirstBlockId = self::readInt4($fh);

        // Skip unused bytes
        fseek($fh, 56);
        // Streams shorter than this are stored using small blocks

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Treat it as corruption: re-obtain the file from its source and retry; compare checksums if available.
  2. Validate the file with another tool first (e.g. 'file report.xls', or opening in LibreOffice) to confirm the container is damaged.
  3. Parse defensively: wrap legacy .xls parsing in try/catch and surface a 'corrupt file' message rather than a library stack trace.
  4. If you accept untrusted uploads, reject files that fail signature+header validation early instead of parsing them.

Example fix

// before
try {
    $ole->read('invoice.xls');
} catch (ReaderException $e) { /* generic */ }

// after
try {
    $ole->read('invoice.xls');
} catch (ReaderException $e) {
    if (str_contains($e->getMessage(), 'Only Little-Endian')) {
        // header corruption — ask the sender for a fresh export
        unlink('invoice.xls');
        throw new RuntimeException('The .xls file is damaged. Please re-export it.', 0, $e);
    }
    throw $e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

$head = (string) @file_get_contents($file, false, null, 28, 2);
if ($head !== "\xFE\xFF") { /* header damaged — reject before OLE parsing */ }

Try / catch

try { $ole->read($file); }
catch (\PhpOffice\PhpSpreadsheet\Reader\Exception $e) {
    if (str_contains($e->getMessage(), 'Little-Endian')) {
        throw new RuntimeException('Workbook container is damaged — please re-export.', 0, $e);
    }
    throw $e;
}

Prevention

When it happens

Trigger: A file that passed the 8-byte OLE signature but whose header bytes at offset 28-29 differ — typically random corruption, a file that begins with a coincidental OLE signature, or a truncated/patched container. Reached only after the signature check in OLE::read(), so it implies the file at least looks like an OLE document at byte 0.

Common situations: Bit-level corruption from bad transfers or disk faults; deliberately crafted files (fuzzing payloads) whose header is nonsense; files produced by broken non-Microsoft writers that emit partial OLE headers.

Related errors


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