{"record":{"id":"89a162c1b195ffe5","repo":"Intervention/image","slug":"failed-to-iterate-image-frames","errorCode":null,"errorMessage":"Failed to iterate image frames","messagePattern":"Failed to iterate image frames","errorType":"exception","errorClass":"Intervention\\Image\\Exceptions\\DriverException","httpStatus":null,"severity":"error","filePath":"src/Drivers/Imagick/Core.php","lineNumber":245,"sourceCode":"            throw new DriverException('Failed to count image frames', previous: $e);\n        }\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @see Iterator::rewind()\n     *\n     * @throws DriverException\n     */\n    public function current(): mixed\n    {\n        try {\n            $this->imagick->setIteratorIndex($this->iteratorIndex);\n\n            return new Frame($this->imagick->current());\n        } catch (ImagickException | RuntimeException $e) {\n            throw new DriverException('Failed to iterate image frames', previous: $e);\n        }\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @see Iterator::rewind()\n     */\n    public function next(): void\n    {\n        $this->iteratorIndex += 1;\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @see Iterator::rewind()\n     */","sourceCodeStart":227,"sourceCodeEnd":263,"githubUrl":"https://github.com/Intervention/image/blob/5598b9e39751c34afc5cdee84abef77f92c26f68/src/Drivers/Imagick/Core.php#L227-L263","documentation":"Thrown by Core::current() (the SPL Iterator implementation) when setIteratorIndex() or Imagick::current() fails while the foreach loop requests the frame at the internal iterator position. Both ImagickException and the library's RuntimeException are wrapped into this DriverException.","triggerScenarios":"Iterating an Imagick core: foreach ($image as $frame) or foreach ($image->core() as $frame), or calling current()/get() explicitly. It fires when the iterator index no longer points at a valid frame — typically because frames were removed (slice/removeImage) during iteration, or the Imagick object was destroyed mid-loop.","commonSituations":"Modifying an animation while looping over it (removing frames inside foreach); long loops where the underlying resource times out or is freed; running array operations that partially consume the iterator then resuming; concurrent access to the same Imagick object from coroutines/parallel workers.","solutions":["Never remove or slice frames inside a foreach over the same image; collect changes first, apply after the loop","Check $e->getPrevious() to distinguish ImagickException (native failure) from RuntimeException (index invalid)","Re-read the image and iterate a fresh copy when resuming after partial processing","Use $image->core()->frame($i) with an explicit index instead of the iterator when you need stable positions"],"exampleFix":"// before: mutating while iterating\nforeach ($image as $i => $frame) {\n    $image->sliceAnimation($i, 1); // invalidates iterator\n}\n\n// after: copy first, then mutate\n$snapshot = $manager->read((string) $image->toGif());\nforeach ($snapshot as $i => $frame) {\n    // safe: mutation happens on $image elsewhere\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"use Intervention\\Image\\Exceptions\\DriverException;\n\ntry {\n    foreach ($image as $frame) {\n        process($frame);\n    }\n} catch (DriverException $e) {\n    // iterator state is invalid; fall back to indexed access\n    for ($i = 0, $n = $reloaded->count(); $i < $n; $i++) {\n        process($reloaded->core()->frame($i));\n    }\n}","preventionTips":["Never remove/slice frames inside a foreach over the same image","Prefer indexed frame($i) loops when you mutate the animation","Do not share one Image between parallel workers or coroutines"],"tags":["imagick","iterator","frames","animation"],"backgroundTag":"image-frame-iteration-failed","analyzedSha":"5598b9e39751c34afc5cdee84abef77f92c26f68","analyzedAt":"2026-08-23T02:17:31.068Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}