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

$bitmap doesn't contain enough data.\n

Error message

$bitmap doesn't contain enough data.\n

What it means

After slurping the file into memory, processBitmap() rejects anything of 54 bytes (0x36) or fewer - smaller than a minimal BMP file header plus info header. This guards the subsequent offset-based unpack() calls from reading garbage. It catches truncated files and placeholder stubs; 0-byte files were already rejected by the previous check.

Source

Thrown at src/PhpSpreadsheet/Writer/Xls/Worksheet.php:2473

     *
     * @return array{0: int, 1: int, 2: int, 3: string} Data and properties of the bitmap
     *
     * @codeCoverageIgnore
     */
    public function processBitmap(string $bitmap): array
    {
        // Open file.
        $bmp_fd = @fopen($bitmap, 'rb');
        if ($bmp_fd === false || 0 === (int) filesize($bitmap)) {
            throw new WriterException("Couldn't import $bitmap");
        }

        // Slurp the file into a string.
        $data = (string) fread($bmp_fd, (int) filesize($bitmap));

        // Check that the file is big enough to be a bitmap.
        if (strlen($data) <= 0x36) {
            throw new WriterException("$bitmap doesn't contain enough data.\n");
        }

        // The first 2 bytes are used to identify the bitmap.

        $identity = unpack('A2ident', $data);
        if ($identity === false || $identity['ident'] != 'BM') {
            throw new WriterException("$bitmap doesn't appear to be a valid bitmap image.\n");
        }

        // Remove bitmap data: ID.
        $data = substr($data, 2);

        // Read and remove the bitmap size. This is more reliable than reading
        // the data size at offset 0x22.
        //
        $size_array = unpack('Vsa', substr($data, 0, 4)) ?: [];
        /** @var int */
        $size = $size_array['sa'];

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Re-download or re-export the original BMP
  2. Verify integrity (size and hash) before calling insertBitmap()
  3. Convert to PNG/JPEG and use the Drawing API instead of raw Xls bitmaps
Defensive patterns

Strategy: validation

Validate before calling

const MIN_BMP_SIZE = 54; // 0x36: file header (14) + info header (40)

if (!is_file($path) || filesize($path) < MIN_BMP_SIZE) {
    throw new InvalidArgumentException("File too small to be a BMP: $path");
}
$worksheetWriter->insertBitmap($row, $col, $path);

Try / catch

try {
    $worksheetWriter->insertBitmap($row, $col, $path);
} catch (\PhpOffice\PhpSpreadsheet\Writer\Exception $e) {
    if (str_contains($e->getMessage(), 'contain enough data')) {
        error_log("Truncated bitmap rejected: $path"); // re-fetch source image
    }
}

Prevention

When it happens

Trigger: A BMP file truncated below 54 bytes (interrupted download), a text/HTML error page saved with a .bmp extension, or a 1-53 byte stub passed to insertBitmap().

Common situations: Interrupted uploads/downloads; proxies or antivirus replacing the file body; unit-test fixtures that are empty shells.

Related errors


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