Intervention/image · error · ImageDecoderException

Unable to Base64-decode image from string

Error message

Unable to Base64-decode image from string

What it means

Thrown by Base64ImageDecoder::decode when decodeBase64Data fails: base64_decode($input, true) returned false, or the decode/re-encode round trip did not match the input. In other words, the string routed to the base64 decoder is not canonical, strictly-valid Base64, so it is rejected with an ImageDecoderException before image decoding begins.

Source

Thrown at src/Drivers/Gd/Decoders/Base64ImageDecoder.php:37

     *
     * @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. Sanitize the string: strip any 'data:...;base64,' prefix, remove whitespace/newlines, and re-pad with '=' to a multiple of 4
  2. If the value is a full data URI, pass it as-is so DataUriImageDecoder handles it, or parse it with DataUri::parse() first
  3. Validate before reading: base64_decode($s, true) !== false && base64_encode(base64_decode($s, true)) === preg_replace('/\s+/', '', $s)
  4. For base64url input, translate '-' => '+', '_' => '/' before handing it over

Example fix

// before
$image = $manager->read($uploadedBase64); // contains "data:image/png;base64," prefix
// ImageDecoderException: Unable to Base64-decode image from string

// after
$b64 = preg_replace('#^data:[^;]+;base64,#', '', $uploadedBase64);
$b64 = str_replace(["\n", "\r", ' '], '', $b64);
$image = $manager->read($b64);
Defensive patterns

Strategy: validation

Validate before calling

function normalizeBase64(string $input): string
{
    $b64 = preg_replace('#^data:[^;]+;base64,#', '', $input);
    $b64 = str_replace(["\n", "\r", ' '], '', $b64);
    return $b64 . str_repeat('=', (4 - strlen($b64) % 4) % 4);
}

$b64 = normalizeBase64($input);
$decoded = base64_decode($b64, true);
if ($decoded === false || base64_encode($decoded) !== $b64) {
    throw new RuntimeException('Not valid canonical Base64');
}

Try / catch

try {
    $image = $manager->read($b64);
} catch (\Intervention\Image\Exceptions\ImageDecoderException $e) {
    if (str_contains($e->getMessage(), 'Base64-decode')) {
        // fix the encoding of the source value; retrying the same string will not help
    }
}

Prevention

When it happens

Trigger: Passing a string ending in '=' that is not well-formed Base64 (that suffix alone makes supports() claim it); strings containing a 'data:image/...;base64,' prefix, whitespace, or URL-safe '-'/'_' alphabet; base64 with stripped padding that fails the base64_encode round-trip check; binary data misrouted into Base64ImageDecoder::decode directly.

Common situations: Frontend sends a data URI where the backend expected bare base64; JSON payloads where newlines were inserted into long base64 strings; copy-paste artifacts (truncated strings, ellipsis); client libraries using base64url (JWT-style) encoding for image payloads.

Related errors


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