Intervention/image · error · Intervention\Image\Exceptions\DriverException
Failed to add image frame
Error message
Failed to add image frame
What it means
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.
Source
Thrown at src/Drivers/Imagick/Core.php:209
try {
$imagick->setImageDelay(
(int) round($frame->delay() * 100),
);
$imagick->setImageDispose($frame->disposalMethod());
$size = $frame->size();
$imagick->setImagePage(
$size->width(),
$size->height(),
$frame->offsetLeft(),
$frame->offsetTop(),
);
$this->imagick->addImage($imagick);
} catch (ImagickException $e) {
throw new DriverException('Failed to add image frame', previous: $e);
}
return $this;
}
/**
* {@inheritdoc}
*
* @see CoreInterface::count()
*
* @throws DriverException
*/
public function count(): int
{
try {
return $this->imagick->getNumberImages();
} catch (ImagickException $e) {
throw new DriverException('Failed to count image frames', previous: $e);View on GitHub (pinned to 5598b9e397)
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
Example fix
// before: adding the same frame object repeatedly
foreach ($sources as $src) {
$image->core()->add($frame);
}
// after: fresh frame per iteration
foreach ($sources as $src) {
$f = $manager->read($src)->core()->first();
$image->core()->add($f);
} Defensive patterns
Strategy: try-catch
Validate before calling
foreach ($frames as $frame) {
if (!$frame->native() instanceof \Imagick) {
throw new InvalidArgumentException('frame native must be Imagick');
}
$frame->setDelay(max(0, $frame->delay()));
$image->core()->add($frame);
} Type guard
function isImagickFrame(FrameInterface $frame): bool
{
return $frame->native() instanceof \Imagick;
} Try / catch
use Intervention\Image\Exceptions\DriverException;
try {
$image->core()->add($frame);
} catch (DriverException $e) {
// frame stack is now possibly inconsistent: rebuild from sources
throw new ImageBuildException('animation assembly failed', $e);
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Failed to iterate image frames
- Failed to load image frame a position
- Frame #
- First frame not found in image
- Last frame not found in image
AI-assisted analysis of Intervention/image@5598b9e397 (2026-08-23).
Data as JSON: /api/errors/5b2fcc15460bdb6b.
Report an issue: GitHub.