{"record":{"id":"58e012f9808fe5b8","repo":"Intervention/image","slug":"failed-to-apply-intervention-image-drivers-gd-modi-58e012","errorCode":null,"errorMessage":"Failed to apply Intervention\\Image\\Drivers\\Gd\\Modifiers\\TrimModifier, unable to create canvas","messagePattern":"Failed to apply Intervention\\\\Image\\\\Drivers\\\\Gd\\\\Modifiers\\\\TrimModifier, unable to create canvas","errorType":"exception","errorClass":"ModifierException","httpStatus":null,"severity":"error","filePath":"src/Drivers/Gd/Modifiers/TrimModifier.php","lineNumber":75,"sourceCode":"     * Copy the given GdImage to a fresh true color canvas that has no transparent color set.\n     *\n     * imagecropauto() internally drops every pixel that matches the image's \"transparent\n     * color\". palette images that were converted to true color while decoding carry over\n     * a bogus transparent color, which would turn all transparent areas opaque during the\n     * crop. transfer the image to a fresh true color canvas without a transparent color\n     * to preserve the alpha channel.\n     *\n     * @throws ModifierException\n     */\n    private function transparencySafeVersion(GdImage $gd): GdImage\n    {\n        $width = imagesx($gd);\n        $height = imagesy($gd);\n\n        $canvas = imagecreatetruecolor($width, $height);\n\n        if ($canvas === false) {\n            throw new ModifierException(\n                'Failed to apply ' . self::class . ', unable to create canvas',\n            );\n        }\n\n        imagealphablending($canvas, false);\n        imagesavealpha($canvas, true);\n\n        // pre-fill with the original transparent color (if any).\n        $transparent = imagecolortransparent($gd);\n        if ($transparent !== -1) {\n            imagefill($canvas, 0, 0, $transparent);\n        }\n\n        // copy resolution to canvas\n        $resolution = imageresolution($gd);\n        if (is_array($resolution) && array_key_exists(0, $resolution) && array_key_exists(1, $resolution)) {\n            imageresolution($canvas, $resolution[0], $resolution[1]);\n        }","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/Intervention/image/blob/5598b9e39751c34afc5cdee84abef77f92c26f68/src/Drivers/Gd/Modifiers/TrimModifier.php#L57-L93","documentation":"The GD trim() modifier first copies the source image onto a fresh truecolor canvas (transparencySafeVersion) so imagecropauto() cannot destroy alpha information. That copy is created with imagecreatetruecolor($width, $height), and it returned false, meaning GD could not allocate the canvas. In practice this is almost always PHP's memory_limit: a truecolor canvas costs roughly width x height x 5 bytes on top of the memory already held by the source image.","triggerScenarios":"Calling trim() on the GD driver for a large image (a 6000x4000 photo needs ~120 MB just for the duplicate canvas) while memory_limit is 128M/256M; pipelines that keep several GdImage buffers alive (resize + trim + watermark) so the extra canvas pushes the request over the limit.","commonSituations":"Phone or camera originals (12-50 MP) trimmed on shared hosting with default memory_limit; long-running queue workers whose memory accumulates over many images; high-DPI scans.","solutions":["Raise the memory budget for the image worker: ini_set('memory_limit', '512M'); or set memory_limit in php.ini / the PHP-FPM pool.","Budget the GD cost up front (about width*height*5 bytes for the trim canvas on top of the source) and reject or downscale oversized inputs with scaleDown() before trim().","Switch the ImageManager to the Imagick driver, which does not allocate a monolithic PHP-memory canvas for trimming.","Move trimming into a dedicated queue job so the operation is not bound by the web request's memory_limit."],"exampleFix":"// before\n$image = ImageManager::gd()->read('poster.tif')->trim();\n\n// after: GD trim() duplicates the image onto a new truecolor canvas (~5 bytes/pixel)\nini_set('memory_limit', '1G');\n$image = ImageManager::gd()->read('poster.tif')->trim();","handlingStrategy":"validation","validationCode":"// GD trim() duplicates the image onto a new truecolor canvas (~5 bytes/pixel)\n$bytesNeeded = $image->width() * $image->height() * 5;\n$bytesFree = return_bytes(ini_get('memory_limit')) - memory_get_usage();\nif ($bytesNeeded > $bytesFree) {\n    $image = $image->scaleDown(width: 4000); // or reject with a clear message\n}\n$image->trim();","typeGuard":null,"tryCatchPattern":"try { $image->trim(); } catch (ModifierException $e) { error_log(...); $image = $image->scaleDown(width: 4000)->trim(); }","preventionTips":["Track width*height of accepted uploads and reject or downscale images whose pixel budget your memory_limit cannot hold twice.","Run image work in dedicated queue workers with a raised memory_limit instead of web requests.","Prefer the Imagick driver for very large sources."],"tags":["gd","trim","memory-limit","imagecreatetruecolor","canvas"],"backgroundTag":"php-memory-limit-exhausted","analyzedSha":"5598b9e39751c34afc5cdee84abef77f92c26f68","analyzedAt":"2026-08-23T02:17:31.068Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}