Intervention/image · error · NotSupportedException

Trim modifier cannot be applied to animated images

Error message

Trim modifier cannot be applied to animated images

What it means

NotSupportedException thrown by the Imagick TrimModifier before any native call: trim is only supported on static images. Trimming an animation would trim each frame against its own background and desync frame geometry, so the modifier fails fast whenever $image->isAnimated() is true. The GD driver throws the identical error.

Source

Thrown at src/Drivers/Imagick/Modifiers/TrimModifier.php:23

namespace Intervention\Image\Drivers\Imagick\Modifiers;

use ImagickException;
use Intervention\Image\Exceptions\ModifierException;
use Intervention\Image\Exceptions\NotSupportedException;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface;
use Intervention\Image\Modifiers\TrimModifier as GenericTrimModifier;

class TrimModifier extends GenericTrimModifier implements SpecializedInterface
{
    /**
     * @throws NotSupportedException
     * @throws ModifierException
     */
    public function apply(ImageInterface $image): ImageInterface
    {
        if ($image->isAnimated()) {
            throw new NotSupportedException('Trim modifier cannot be applied to animated images');
        }

        $imagick = $image->core()->native();

        try {
            $result = $imagick->trimImage(($this->tolerance / 100 * $imagick->getQuantum()) / 1.5)
                && $imagick->setImagePage(0, 0, 0, 0);

            if ($result === false) {
                throw new ModifierException(
                    'Failed to apply ' . self::class . ', unable to processs image trimming',
                );
            }
        } catch (ImagickException $e) {
            throw new ModifierException(
                'Failed to apply ' . self::class . ', unable to processs image trimming',
                previous: $e,
            );

View on GitHub (pinned to 5598b9e397)

Solutions

  1. Check $image->isAnimated() before trimming and branch the pipeline
  2. Reduce to a single frame first: $image = $image->sliceAnimation(0, 1); then trim
  3. Read the file with decodeAnimation: false in the driver config when only a static result is needed
  4. For animated sources, trim one representative frame to compute the crop, then apply crop() to the whole animation instead

Example fix

// before
$image->trim(); // animated GIF -> NotSupportedException

// after
if ($image->isAnimated()) {
    $image = $image->sliceAnimation(0, 1); // first frame only
}
$image->trim();
Defensive patterns

Strategy: validation

Validate before calling

if ($image->isAnimated()) {
    $image = $image->sliceAnimation(0, 1); // reduce to first frame
}
$image->trim($tolerance);

Type guard

function isTrimmable(ImageInterface $image): bool
{
    return !$image->isAnimated();
}

Prevention

When it happens

Trigger: $image->trim($tolerance) on a multi-frame image: animated GIF, animated WebP, or APNG loaded with animation decoding enabled (decodeAnimation defaults to true) on the Imagick driver.

Common situations: Running a generic 'trim borders' pipeline over mixed uploads that include animated GIFs; trimming user avatars or stickers that turn out to be animated; processing animation formats with a pipeline written for photos.

Related errors


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