Intervention/image · error · ModifierException

Failed to apply Intervention\Image\Drivers\Gd\Modifiers\Trim

Error message

Failed to apply Intervention\Image\Drivers\Gd\Modifiers\TrimModifier, unable to determine average color for process

What it means

Before trimming, the GD driver samples the four corner pixels to average a trim base color; imagecolorat() returned false for one of them. GD only returns false there when the GdImage handle is invalid or the coordinates lie outside the image, and the corner coordinates (width-1, height-1) are derived from the image itself — so the underlying GD resource is corrupted or was destroyed, not that the trim options were wrong.

Source

Thrown at src/Drivers/Gd/Modifiers/TrimModifier.php:127

        $green = 0;
        $blue = 0;
        $alpha = 0;

        // corner coordinates
        $size = $image->size();
        $cornerPoints = [
            new Point(0, 0),
            new Point($size->width() - 1, 0),
            new Point(0, $size->height() - 1),
            new Point($size->width() - 1, $size->height() - 1),
        ];

        // create an average color to be used in trim operation
        foreach ($cornerPoints as $pos) {
            $cornerColor = imagecolorat($image->core()->native(), $pos->x(), $pos->y());

            if ($cornerColor === false) {
                throw new ModifierException(
                    'Failed to apply ' . self::class . ', unable to determine average color for process',
                );
            }

            try {
                $rgb = imagecolorsforindex($image->core()->native(), $cornerColor);
            } catch (ValueError) {
                throw new ModifierException(
                    'Failed to apply ' . self::class . ', unable to read trim color from index',
                );
            }

            $red += round(round($rgb['red'] / 51) * 51);
            $green += round(round($rgb['green'] / 51) * 51);
            $blue += round(round($rgb['blue'] / 51) * 51);
            $alpha += $rgb['alpha'];
        }

View on GitHub (pinned to 5598b9e397)

Solutions

  1. Validate the source file is fully decodable before handing it over: getimagesize() must not return false and dimensions must be >= 1.
  2. Re-read the image from the original binary to obtain a clean GdImage and retry trim(); if it fails again, quarantine the file.
  3. Audit any code that touches $image->core()->native() directly (imagedestroy, imagecopy onto freed handles) and remove it.

Example fix

// before
$image = $manager->read($request->file('photo')->getPathname())->trim();

// after: reject files GD cannot fully decode before trimming
$path = $request->file('photo')->getPathname();
if (getimagesize($path) === false) {
    throw new RuntimeException('Uploaded file is not a valid image');
}
$image = $manager->read($path)->trim();
Defensive patterns

Strategy: try-catch

Validate before calling

if (getimagesize($path) === false) {
    throw new RuntimeException('Uploaded file is not a valid image');
}

Try / catch

try { $image->trim(); } catch (ModifierException $e) { /* poisoned input: log hash, quarantine file, skip */ }

Prevention

When it happens

Trigger: trim() on an image whose GD resource was already freed or corrupted: external code called imagedestroy() on core()->native(), a previous operation failed mid-decode and left a broken buffer, or a truncated PNG/GIF decoded to a resource with reported dimensions but unreadable pixel data.

Common situations: Processing truncated or bit-flipped uploads that passed a superficial MIME check; mixing raw GD calls with Intervention Image operations on the same native resource; GD instability after a prior out-of-memory condition.

Related errors


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