Intervention/image · error · ImageDecoderException
Failed to decode GIF format
Error message
Failed to decode GIF format
What it means
Thrown by the GD driver when a GIF is decoded with animation decoding disabled (config option decodeAnimation=false). In that mode the decoder calls imagecreatefromgif()/imagecreatefromstring() and both return false, so the raw bytes could not be parsed as a GIF at all. The input is typically truncated, corrupt, or not actually GIF data.
Source
Thrown at src/Drivers/Gd/Decoders/NativeObjectDecoder.php:82
/**
* Decode image from given GIF source which can be either a file path or binary data.
*
* Depending on the configuration, this is taken over by the native GD function
* or, if animations are required, by our own extended decoder.
*
* @throws InvalidArgumentException
* @throws ImageDecoderException
* @throws DriverException
* @throws StateException
*/
protected function decodeGif(string $input): ImageInterface
{
// create non-animated image depending on config
if ($this->driver()->config()->decodeAnimation === false) {
$native = $this->isGifFormat($input) ? @imagecreatefromstring($input) : @imagecreatefromgif($input);
if ($native === false) {
throw new ImageDecoderException('Failed to decode GIF format');
}
$image = self::decode($native);
$image->origin()->setMediaType('image/gif');
return $image;
}
try {
// create empty core
$core = new Core();
// add frames to core
$splitter = GifSplitter::decode($input)
->split()
->flatten()
->each(function (GdImage $native, int $delay) use ($core): void {
$core->push(new Frame($native, $delay / 100));View on GitHub (pinned to 5598b9e397)
Solutions
- Verify the input really is a GIF before decoding: (new finfo())->buffer($data) or getimagesize()
- If corrupt, re-download or reject the source instead of retrying the same bytes
- Check gd_info() in the failing environment includes GIF support
- Switch the manager to the Imagick driver (ImageManager::usingDriver(ImagickDriver::class)) which tolerates more GIF variants
- Wrap reads in try/catch on ImageDecoderException and quarantine bad files
Example fix
// before
$image = $manager->read($uploadPath); // throws on corrupt GIF
// after
$mime = (new finfo())->file($uploadPath);
if (!str_starts_with($mime, 'image/')) {
throw new RuntimeException('Unsupported or corrupt image: ' . $mime);
}
$image = $manager->read($uploadPath); Defensive patterns
Strategy: try-catch
Validate before calling
$data = file_get_contents($path);
if (!str_starts_with((new finfo())->buffer($data), 'image/gif')) {
throw new InvalidArgumentException('Source is not a GIF');
}
$manager->read($data); Try / catch
try {
$image = $manager->read($gifData);
} catch (ImageDecoderException $e) {
// reject upload, log, or re-fetch the source
} Prevention
- Validate uploads with finfo/getimagesize before processing
- Check HTTP status when downloading remote images
- Do not retry decode on identical corrupt bytes
When it happens
Trigger: ImageManager with the GD driver and option ['decodeAnimation' => false], then ->read($gifData) where $gifData is a truncated upload, a renamed non-GIF file (e.g. an HTML error page saved as .gif), or a GIF on a GD build without GIF read support.
Common situations: User uploads cut off mid-transfer (upload_max_filesize or client abort), fetching remote images without checking the HTTP status so an error body is decoded, files corrupted by ASCII-mode FTP transfers, unusual shared-hosting GD builds.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- The specified index is outside of the range
- Frame #${position} could not be found in the image
- Failed to encode image to GIF format
- Trim modifier cannot be applied to animated images
- Class '{objectShortname}' is not supported by {id} driver
AI-assisted analysis of Intervention/image@5598b9e397 (2026-08-23).
Data as JSON: /api/errors/ae78465eb51ec573.
Report an issue: GitHub.