PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception
Value cannot be converted to an image
Error message
Value cannot be converted to an image
What it means
MemoryDrawing::fromString() turns raw binary into a GD resource via @imagecreatefromstring(); when GD returns false, the string is not a decodable image in any format your GD build supports, and the exception is thrown. Common culprits are base64 payloads that were not decoded (or double-encoded) and formats like WEBP/AVIF on a GD compiled without them.
Source
Thrown at src/PhpSpreadsheet/Worksheet/MemoryDrawing.php:143
* @throws Exception
*/
public static function fromStream($imageStream): self
{
$streamValue = stream_get_contents($imageStream);
return self::fromString($streamValue);
}
/**
* @param string $imageString String data to be converted to a Memory Drawing
*
* @throws Exception
*/
public static function fromString(string $imageString): self
{
$gdImage = @imagecreatefromstring($imageString);
if ($gdImage === false) {
throw new Exception('Value cannot be converted to an image');
}
$mimeType = self::identifyMimeType($imageString);
if (imageistruecolor($gdImage) || imagecolortransparent($gdImage) >= 0) {
imagesavealpha($gdImage, true);
}
$renderingFunction = self::identifyRenderingFunction($mimeType);
$drawing = new self();
$drawing->setImageResource($gdImage);
$drawing->setRenderingFunction($renderingFunction);
$drawing->setMimeType($mimeType);
return $drawing;
}
/** @return callable-string */
private static function identifyRenderingFunction(string $mimeType): stringView on GitHub (pinned to 65b080eef4)
Solutions
- Strip any data-URI prefix and base64_decode() the payload before calling fromString().
- Pre-validate with getimagesizefromstring($binary) — it returns false for undecodable data and reports the type otherwise.
- Check gd_info() for the formats your inputs need and convert unsupported formats server-side.
Example fix
// before
$drawing = MemoryDrawing::fromString($base64FromApi); // encoded string -> throws
// after
$binary = str_starts_with($base64FromApi, 'data:')
? base64_decode(substr($base64FromApi, strpos($base64FromApi, ',') + 1), true)
: base64_decode($base64FromApi, true);
if ($binary === false || getimagesizefromstring($binary) === false) {
throw new InvalidArgumentException('payload is not a decodable image');
}
$drawing = MemoryDrawing::fromString($binary); Defensive patterns
Strategy: validation
Validate before calling
$binary = $data;
if (str_starts_with($data, 'data:')) {
$binary = base64_decode(substr($data, strpos($data, ',') + 1), true);
}
if ($binary === false || getimagesizefromstring($binary) === false) {
throw new InvalidArgumentException('payload is not a decodable image');
}
$drawing = MemoryDrawing::fromString($binary); Type guard
function isDecodableImageString(string $bytes): bool
{
return getimagesizefromstring($bytes) !== false;
} Try / catch
try {
$drawing = MemoryDrawing::fromString($payload);
} catch (PhpSpreadsheetException $e) {
// payload was not decodable: log, skip the image, or request a re-upload
} Prevention
- Strip data: URI prefixes and base64_decode exactly once
- Pre-check every payload with getimagesizefromstring() before conversion
- When inputs may be WEBP/AVIF, confirm the running GD supports them via gd_info()
When it happens
Trigger: fromString($base64) where the value is still the base64 text or still has the 'data:image/png;base64,' prefix; binary from a truncated download; WEBP bytes on a GD build without webp support.
Common situations: Images pasted from HTML editors or received from APIs as data URIs; reading embedded media from untrusted XLSX files; forgetting base64_decode() or applying it twice; environment differences in GD format support.
Related errors
- Could not clone image resource
- Could not get image alpha color
- Unsupported binary comparison operator
- Cloning the calculation engine is not allowed!
- Unsupported numeric binary operation
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/2e3805fbc212a9c6.
Report an issue: GitHub.