PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Writer\Exception
Unable to create image from $filename
Error message
Unable to create image from $filename
What it means
BIFF8 (Xls) has no native GIF blip type, so the Xls writer converts every GIF drawing to PNG using GD's imagecreatefromgif() before embedding it. If that function returns false - corrupt/truncated GIF, unreadable path, or a GD build without GIF read support - this Exception is thrown while writing the workbook.
Source
Thrown at src/PhpSpreadsheet/Writer/Xls.php:449
}
private static int $two = 2; // phpstan silliness
private function processDrawing(BstoreContainer &$bstoreContainer, Drawing $drawing): void
{
$blipType = 0;
$blipData = '';
$filename = $drawing->getPath();
$imageSize = getimagesize($filename);
$imageFormat = empty($imageSize) ? 0 : ($imageSize[self::$two] ?? 0);
switch ($imageFormat) {
case 1: // GIF, not supported by BIFF8, we convert to PNG
$blipType = BSE::BLIPTYPE_PNG;
$newImage = @imagecreatefromgif($filename);
if ($newImage === false) {
throw new Exception("Unable to create image from $filename");
}
ob_start();
imagepng($newImage);
$blipData = ob_get_contents();
ob_end_clean();
break;
case 2: // JPEG
$blipType = BSE::BLIPTYPE_JPEG;
$blipData = file_get_contents($filename);
break;
case 3: // PNG
$blipType = BSE::BLIPTYPE_PNG;
$blipData = file_get_contents($filename);
break;
case 6: // Windows DIB (BMP), we convert to PNGView on GitHub (pinned to 65b080eef4)
Solutions
- Validate images before attaching: getimagesize() must succeed and report IMAGETYPE_GIF, and function_exists('imagecreatefromgif') must be true.
- Re-encode GIFs to PNG server-side before adding the drawing - Xls embeds PNGs natively with no conversion step.
- Reject or quarantine unreadable uploads at ingestion time instead of at export time.
- Ensure GD is installed with GIF support (php -i | grep GD) in the deployment image.
Example fix
// before
$drawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing();
$drawing->setPath($uploadedPath); // corrupt .gif => throws during save()
// after
$size = @getimagesize($uploadedPath);
if ($size === false || $size[2] !== IMAGETYPE_GIF || !function_exists('imagecreatefromgif')) {
$uploadedPath = reencodeAsPng($uploadedPath); // or reject the file
}
$drawing->setPath($uploadedPath); Defensive patterns
Strategy: validation
Validate before calling
/** @param Worksheet[] $sheets */
function assertImagesReadableForXls(array $sheets): void
{
foreach ($sheets as $sheet) {
foreach ($sheet->getDrawingCollection() as $drawing) {
$path = $drawing->getPath();
$info = @getimagesize($path);
if ($info === false) {
throw new RuntimeException("Unreadable image: $path");
}
if ($info[2] === IMAGETYPE_GIF && !function_exists('imagecreatefromgif')) {
throw new RuntimeException('GD lacks GIF support; convert ' . $path . ' to PNG');
}
}
}
}
assertImagesReadableForXls($spreadsheet->getAllSheets()); Prevention
- Verify uploads with getimagesize() (content sniffing), not extension or MIME header.
- Re-encode all raster images to PNG/PNG-compatible formats at ingestion so no runtime GD conversion is needed.
- Ensure local copies of remote images exist before export; GD needs seekable streams.
- Include GD format support in your image build's smoke test (php -r 'var_dump(function_exists("imagecreatefromgif"));').
When it happens
Trigger: A worksheet drawing (setPath() to a .gif) whose file is corrupt or partially uploaded; the path points at a stream wrapper GD cannot seek/read; PHP's GD extension compiled without --with-gif read support, making imagecreatefromgif() undefined or failing.
Common situations: User-uploaded images validated only by file extension; images fetched from object stores (s3://) without a local copy; truncated uploads; minimal Alpine/Debian container images where GD lacks format support.
Related errors
- Unsupported BIFF8 constant
- Not a cell range address
- A Worksheet has already been assigned. Drawings can only exi
- Required floating point format not supported on this platfor
- Unknown token $token
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/b962ee9b60cbeedc.
Report an issue: GitHub.