Intervention/image · error · Intervention\Image\Exceptions\ImageDecoderException
Unable to Base64-decode image from string
Error message
Unable to Base64-decode image from string
What it means
Thrown by the Imagick Base64ImageDecoder when its helper decodeBase64Data() rejects the input as not valid Base64 — the string contains characters or padding that strict base64 decoding refuses. It is an ImageDecoderException raised from ImageManager::read() when auto-detection routed a string here.
Source
Thrown at src/Drivers/Imagick/Decoders/Base64ImageDecoder.php:36
*
* @see DecoderInterface::supports()
*/
public function supports(mixed $input): bool
{
return $this->couldBeBase64Data($input);
}
/**
* {@inheritdoc}
*
* @see DecoderInterface::decode()
*/
public function decode(mixed $input): ImageInterface
{
try {
$data = $this->decodeBase64Data($input);
} catch (DecoderException) {
throw new ImageDecoderException('Unable to Base64-decode image from string');
}
try {
return parent::decode($data);
} catch (DecoderException) {
throw new ImageDecoderException('Base64-encoded data contains unsupported image type');
}
}
}
View on GitHub (pinned to 5598b9e397)
Solutions
- Strip the data URI scheme prefix before reading: remove everything through the first comma
- Normalize URL-safe alphabet and whitespace: strtr($s, '-_', '+/') and preg_replace('/\s+/', '', $s)
- Validate before decoding with base64_decode($s, true) and a re-encode comparison
- If the input is a data URI, pass it as-is — the manager's DataUriImageDecoder handles the scheme; only raw base64 should reach the base64 path
Example fix
// before: full data URI handed to the base64 path $image = $manager->read($dataUriString); // after: strip scheme, keep raw base64 $base64 = substr($dataUriString, strpos($dataUriString, ',') + 1); $image = $manager->read($base64); // or simply: $manager->read($dataUriString) works when passed unchanged, // because supports() routes data URIs to DataUriImageDecoder
Defensive patterns
Strategy: validation
Validate before calling
// keep only pure base64, then verify round-trip
$s = preg_replace('/\s+/', '', $input);
$s = strtr($s, '-_', '+/');
$decoded = base64_decode($s, true);
if ($decoded === false || base64_encode($decoded) !== rtrim($s, '=')) {
throw new InvalidArgumentException('input is not valid base64');
} Type guard
function looksLikeBase64(string $s): bool
{
return preg_match('/^[A-Za-z0-9+\/+]{4}(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/', $s) === 1;
} Try / catch
use Intervention\Image\Exceptions\ImageDecoderException;
try {
$image = $manager->read($base64);
} catch (ImageDecoderException $e) {
// either invalid base64 or unsupported payload; report to the uploader
return back()->withErrors(['image' => 'Invalid image data']);
} Prevention
- Strip data URI prefixes before treating a string as raw base64
- Normalize URL-safe base64 (- _) back to + / and remove whitespace
- Prefer passing data URIs untouched to read() so decoder routing handles them
When it happens
Trigger: Passing $manager->read($string) where $string is not pure base64: a full data URI still carrying the 'data:image/png;base64,' prefix; URL-safe base64 (- and _); missing padding; embedded whitespace/newlines from being transmitted in JSON or a textarea; base64 of nothing.
Common situations: Frontend sends a data URI (from canvas.toDataURL or a file-reader) and the backend feeds it to read() whole; base64 stored after RFC 4648 URL-safe encoding; strings truncated by URL length limits or copy-paste; payloads re-encoded through form submissions that escape '+' into spaces.
Related errors
- Input is not valid Base64-encoded data
- Image source must be data uri scheme of type string or
- Base64-encoded data must be either of type string or instanc
- Unable to Base64-decode image from string
- Base64-encoded data contains unsupported image type
AI-assisted analysis of Intervention/image@5598b9e397 (2026-08-23).
Data as JSON: /api/errors/61011599c7bafaca.
Report an issue: GitHub.