{"record":{"id":"4b7db62472a9ca5d","repo":"Intervention/image","slug":"failed-to-apply-class-unable-to-rotate-image","errorCode":null,"errorMessage":"Failed to apply {class}, unable to rotate image","messagePattern":"Failed to apply (.+?), unable to rotate image","errorType":"exception","errorClass":"Intervention\\Image\\Exceptions\\ModifierException","httpStatus":null,"severity":"error","filePath":"src/Drivers/Imagick/Modifiers/RotateModifier.php","lineNumber":31,"sourceCode":"\nclass RotateModifier extends GenericRotateModifier implements SpecializedInterface\n{\n    /**\n     * @throws ModifierException\n     * @throws StateException\n     */\n    public function apply(ImageInterface $image): ImageInterface\n    {\n        $background = $this->driver()\n            ->colorProcessor($image)\n            ->export($this->backgroundColor());\n\n        foreach ($image as $frame) {\n            try {\n                $result = $frame->native()->rotateImage($background, $this->rotationAngle());\n\n                if ($result === false) {\n                    throw new ModifierException(\n                        'Failed to apply ' . self::class . ', unable to rotate image',\n                    );\n                }\n\n                // Reset the virtual canvas page that rotateImage() leaves behind. A\n                // non-right angle produces a negative page offset which otherwise\n                // corrupts the animated-AVIF (libheif sequences) writer, leaving the\n                // bottom/right region transparent. Mirrors TrimModifier/CoverModifier.\n                $frame->native()->setImagePage(0, 0, 0, 0);\n            } catch (ImagickException $e) {\n                throw new ModifierException(\n                    'Failed to apply ' . self::class . ', unable to rotate image',\n                    previous: $e,\n                );\n            }\n        }\n\n        return $image;","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/Intervention/image/blob/5598b9e39751c34afc5cdee84abef77f92c26f68/src/Drivers/Imagick/Modifiers/RotateModifier.php#L13-L49","documentation":"rotate() exports the background color through the driver's color processor, then calls Imagick::rotateImage($background, $angle) per frame; a false return triggers this ModifierException before the follow-up setImagePage() canvas reset runs. Non-right angles grow the canvas up to the diagonal (sqrt(2) x each side for 45 degrees), so memory and ImageMagick width/height policy caps are the classic failure sources. The exception aborts mid-loop, leaving earlier frames already rotated.","triggerScenarios":"$image->rotate(45) on a large image whose rotated canvas exceeds policy.xml width/height/area limits or the PHP memory_limit; a background color whose exported native format the frame rejects.","commonSituations":"Free-angle rotation features on user photos (straightening sliders) in workers with tight memory; hardened shared hosts with strict ImageMagick policies; rotating already-large panoramas by odd angles.","solutions":["Estimate the rotated canvas (diagonal = sqrt(w^2 + h^2)) and downscale first if it exceeds your limits","Raise PHP memory_limit and policy.xml width/height/area caps for legitimate large rotations","Prefer right angles (90/180/270) where the canvas does not grow","Inspect $e->getPrevious()?->getMessage() (null on this branch) or Imagick::getResourceLimit() when diagnosing"],"exampleFix":"// before\n$image->rotate(45); // full-size 4000x3000 photo\n\n// after\n$diagonal = (int) ceil(hypot($image->width(), $image->height()));\nif ($diagonal > 8000) {\n    $image->resize(2000, null); // shrink before a free-angle rotate\n}\n$image->rotate(45);","handlingStrategy":"try-catch","validationCode":"$diagonal = (int) ceil(hypot($image->width(), $image->height()));\n$maxSide = 8192; // keep below policy.xml caps and memory budget\nif ($diagonal > $maxSide) {\n    $scale = $maxSide / $diagonal;\n    $image->resize((int) round($image->width() * $scale), (int) round($image->height() * $scale));\n}\n$image->rotate($angle);","typeGuard":null,"tryCatchPattern":"use Intervention\\Image\\Exceptions\\ModifierException;\n\ntry {\n    $image->rotate(45);\n} catch (ModifierException $e) {\n    $msg = $e->getPrevious()?->getMessage() ?? '';\n    if (str_contains($msg, 'limit') || str_contains($msg, 'memory')) {\n        // canvas grew past limits: pre-downscale and retry, or reject the angle\n    } else {\n        throw $e;\n    }\n}","preventionTips":["Estimate the post-rotation canvas with hypot(w, h) and pre-scale large images before free-angle rotates","Snap user-supplied angles near 90/180/270 to exact right angles to avoid canvas growth entirely","Note the modifier loops frames: on animated images earlier frames may already be rotated when the exception fires"],"tags":["php","imagick","intervention-image","rotate","rotateimage","memory-limit"],"backgroundTag":"image-rotation-failed","analyzedSha":"5598b9e39751c34afc5cdee84abef77f92c26f68","analyzedAt":"2026-08-23T02:17:31.068Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}