{"record":{"id":"c5ae8eb4bd9ef4c0","repo":"Intervention/image","slug":"failed-to-set-image-loop-count","errorCode":null,"errorMessage":"Failed to set image loop count","messagePattern":"Failed to set image loop count","errorType":"exception","errorClass":"Intervention\\Image\\Exceptions\\DriverException","httpStatus":null,"severity":"error","filePath":"src/Drivers/Imagick/Core.php","lineNumber":376,"sourceCode":"        } catch (ImagickException $e) {\n            throw new DriverException('Failed to get image loop count', previous: $e);\n        }\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @see CoreInterface::setLoops()\n     *\n     * @throws DriverException\n     */\n    public function setLoops(int $loops): CoreInterface\n    {\n        try {\n            $this->imagick->resetIterator();\n            $this->imagick->setImageIterations($loops);\n        } catch (ImagickException $e) {\n            throw new DriverException('Failed to set image loop count', previous: $e);\n        }\n\n        return $this;\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @see CollectionInterface::first()\n     *\n     * @throws DriverException\n     * @throws StateException\n     */\n    public function first(): FrameInterface\n    {\n        try {\n            return $this->frame(0);\n        } catch (InvalidArgumentException $e) {","sourceCodeStart":358,"sourceCodeEnd":394,"githubUrl":"https://github.com/Intervention/image/blob/5598b9e39751c34afc5cdee84abef77f92c26f68/src/Drivers/Imagick/Core.php#L358-L394","documentation":"Thrown by Core::setLoops() when resetIterator() or setImageIterations() raises an ImagickException. It is reached from $image->setLoops($n), which is how you control how many extra times an animated GIF/WebP replays. The native calls fail on invalid values or on a core with no readable frame at the iterator position.","triggerScenarios":"$image->setLoops(-1) (ImageMagick rejects negative iteration counts); calling setLoops() on an empty/destroyed core (no frames for the iterator to select); calling it after operations that left the Imagick stack malformed.","commonSituations":"Passing an unvalidated user setting for animation loops (e.g. -1 meaning 'infinite' is not valid here; 0 loops forever in GIF terms); building animations from scratch and setting loops before any frame was added; chaining setLoops after a failed slice.","solutions":["Clamp the value: setLoops(max(0, $loops)) — non-negative integers only","Ensure the image actually has frames: count($image) > 0 before setting loops","On corruption suspicion, re-read the source and apply setLoops immediately after read"],"exampleFix":"// before: user input passed through\n$image->setLoops($request->input('loops')); // -1 crashes\n\n// after: clamp to valid range\n$image->setLoops(max(0, (int) $request->integer('loops')));","handlingStrategy":"validation","validationCode":"$loops = max(0, (int) $loops);\nif ($image->count() > 0) {\n    $image->setLoops($loops);\n}","typeGuard":"function isValidLoopCount(mixed $value): bool\n{\n    return is_int($value) && $value >= 0;\n}","tryCatchPattern":"use Intervention\\Image\\Exceptions\\DriverException;\n\ntry {\n    $image->setLoops($loops);\n} catch (DriverException $e) {\n    throw new RuntimeException('Could not apply animation loop count', $e);\n}","preventionTips":["Clamp user-supplied loop counts to integers >= 0 (0 = infinite in GIF semantics)","Only call setLoops() on images with at least one frame","Validate animation options in form requests before they reach image code"],"tags":["imagick","animation","gif","loops","validation"],"backgroundTag":"animation-loop-count-set-failed","analyzedSha":"5598b9e39751c34afc5cdee84abef77f92c26f68","analyzedAt":"2026-08-23T02:17:31.068Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}