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

  1. Strip the data URI scheme prefix before reading: remove everything through the first comma
  2. Normalize URL-safe alphabet and whitespace: strtr($s, '-_', '+/') and preg_replace('/\s+/', '', $s)
  3. Validate before decoding with base64_decode($s, true) and a re-encode comparison
  4. 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

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


AI-assisted analysis of Intervention/image@5598b9e397 (2026-08-23). Data as JSON: /api/errors/61011599c7bafaca. Report an issue: GitHub.