Intervention/image · error · ImageDecoderException

Failed to read media (MIME) type from binary data

Error message

Failed to read media (MIME) type from binary data

What it means

Thrown by mediaTypeByBinary when both detection paths fail on binary data: finfo is unavailable or returned nothing usable, and @getimagesizefromstring() did not return an array (i.e. PHP does not recognize the bytes as any known image format). Unlike the 'Unsupported media type' errors, here detection itself failed, which almost always means the data is not an image at all or is truncated/corrupt.

Source

Thrown at src/Drivers/Gd/Decoders/AbstractDecoder.php:84

     * @throws NotSupportedException
     */
    protected function mediaTypeByBinary(string $data): MediaType
    {
        if (function_exists('finfo_buffer') && function_exists('finfo_open')) {
            $mediaType = finfo_buffer(finfo_open(FILEINFO_MIME_TYPE), $data);
            if (is_string($mediaType)) {
                try {
                    return MediaType::from($mediaType);
                } catch (ValueError | TypeError) {
                    throw new NotSupportedException('Unsupported media type (MIME) ' . $mediaType . '.');
                }
            }
        }

        $info = @getimagesizefromstring($data);

        if (!is_array($info)) {
            throw new ImageDecoderException('Failed to read media (MIME) type from binary data');
        }

        try {
            return MediaType::from($info['mime']);
        } catch (ValueError | TypeError) {
            throw new NotSupportedException('Unsupported media type (MIME) ' . $info['mime'] . '.');
        }
    }
}

View on GitHub (pinned to 5598b9e397)

Solutions

  1. Check what the bytes actually are before decoding: $info = @getimagesizefromstring($data); it returns false for non-images
  2. If the data was supposed to be base64, decode it first or pass it through the proper input channel so the Base64ImageDecoder handles it
  3. Re-fetch or repair the source: verify transfer length/checksum, retry the download, or re-export the original file
  4. Assert the upstream HTTP response (status + Content-Type) before treating a body as image data

Example fix

// before
$image = $manager->read($response->getBody()->getContents());
// ImageDecoderException: Failed to read media (MIME) type from binary data

// after
$body = $response->getBody()->getContents();
if (@getimagesizefromstring($body) === false) {
    throw new RuntimeException('Upstream did not return an image: ' . substr($body, 0, 120));
}
$image = $manager->read($body);
Defensive patterns

Strategy: try-catch

Validate before calling

if (@getimagesizefromstring($data) === false && (new \finfo(FILEINFO_MIME_TYPE))->buffer($data) === 'application/octet-stream') {
    throw new RuntimeException('Payload is not recognizable image data');
}

Try / catch

try {
    $image = $manager->read($data);
} catch (\Intervention\Image\Exceptions\ImageDecoderException $e) {
    // bytes are not an image; log a prefix of the payload for diagnosis
    logger()->debug('Non-image payload: ' . substr(bin2hex($data), 0, 32));
}

Prevention

When it happens

Trigger: Calling ImageManager::read($string) with random bytes, an HTML/JSON error page captured as a body, a truncated upload (partial multipart read, clipped base64), or an encrypted/encoded payload that was never base64-decoded first. Also hit directly via decodeBinary, which calls mediaTypeByBinary after imagecreatefromstring succeeds.

Common situations: cURL/Guzzle response bodies passed to read() without checking Content-Type or success; failed downloads saved to disk then reopened; upstream API returning XML error envelope instead of image bytes; PHP builds compiled without the fileinfo extension where only getimagesizefromstring can judge.

Related errors


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