{"record":{"id":"5b2fcc15460bdb6b","repo":"Intervention/image","slug":"failed-to-add-image-frame","errorCode":null,"errorMessage":"Failed to add image frame","messagePattern":"Failed to add image frame","errorType":"exception","errorClass":"Intervention\\Image\\Exceptions\\DriverException","httpStatus":null,"severity":"error","filePath":"src/Drivers/Imagick/Core.php","lineNumber":209,"sourceCode":"\n        try {\n            $imagick->setImageDelay(\n                (int) round($frame->delay() * 100),\n            );\n\n            $imagick->setImageDispose($frame->disposalMethod());\n\n            $size = $frame->size();\n            $imagick->setImagePage(\n                $size->width(),\n                $size->height(),\n                $frame->offsetLeft(),\n                $frame->offsetTop(),\n            );\n\n            $this->imagick->addImage($imagick);\n        } catch (ImagickException $e) {\n            throw new DriverException('Failed to add image frame', previous: $e);\n        }\n\n        return $this;\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @see CoreInterface::count()\n     *\n     * @throws DriverException\n     */\n    public function count(): int\n    {\n        try {\n            return $this->imagick->getNumberImages();\n        } catch (ImagickException $e) {\n            throw new DriverException('Failed to count image frames', previous: $e);","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/Intervention/image/blob/5598b9e39751c34afc5cdee84abef77f92c26f68/src/Drivers/Imagick/Core.php#L191-L227","documentation":"Thrown by Core::add() when appending a FrameInterface to the Imagick core fails. add() copies delay, disposal method and page geometry onto the frame's native Imagick object and then calls Imagick::addImage(); any ImagickException during those steps is rethrown as this DriverException.","triggerScenarios":"Calling $image->core()->add($frame) or push($frame) (used when composing animations manually) where the frame's native() is not a usable Imagick single-frame object: it was already added to another stack and consumed, was cleared/destroyed, belongs to a different driver, or delay()/disposalMethod() return values Imagick rejects (e.g. negative delay).","commonSituations":"Building a GIF animation frame-by-frame and reusing the same source frame object twice; mixing GD-decoded frames into an Imagick core; adding frames after the target Imagick object was destroyed; passing a frame whose delay was computed as negative from bad timing data.","solutions":["Inspect $e->getPrevious() for the underlying ImagickException message","Create a fresh frame (or clone its native Imagick) for each add() call instead of reusing one instance","Ensure every frame comes from the same Imagick driver pipeline ($frame->native() instanceof Imagick)","Validate delay: $frame->setDelay(max(0, $delay)) before adding","Wrap animation assembly in try/catch on DriverException and abort the batch on failure"],"exampleFix":"// before: adding the same frame object repeatedly\nforeach ($sources as $src) {\n    $image->core()->add($frame);\n}\n\n// after: fresh frame per iteration\nforeach ($sources as $src) {\n    $f = $manager->read($src)->core()->first();\n    $image->core()->add($f);\n}","handlingStrategy":"try-catch","validationCode":"foreach ($frames as $frame) {\n    if (!$frame->native() instanceof \\Imagick) {\n        throw new InvalidArgumentException('frame native must be Imagick');\n    }\n    $frame->setDelay(max(0, $frame->delay()));\n    $image->core()->add($frame);\n}","typeGuard":"function isImagickFrame(FrameInterface $frame): bool\n{\n    return $frame->native() instanceof \\Imagick;\n}","tryCatchPattern":"use Intervention\\Image\\Exceptions\\DriverException;\n\ntry {\n    $image->core()->add($frame);\n} catch (DriverException $e) {\n    // frame stack is now possibly inconsistent: rebuild from sources\n    throw new ImageBuildException('animation assembly failed', $e);\n}","preventionTips":["Never add the same Frame instance twice; create or clone a fresh frame per add()","Keep all frames within one driver pipeline (decode and compose with the same ImageManager)","Clamp delays to non-negative values before adding frames"],"tags":["imagick","animation","frames","compose"],"backgroundTag":"add-animation-frame-failed","analyzedSha":"5598b9e39751c34afc5cdee84abef77f92c26f68","analyzedAt":"2026-08-23T02:17:31.068Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}