Intervention/image · error · DriverException
Failed to set frame disposal method
Error message
Failed to set frame disposal method
What it means
Frame::setDelay() stores the animation delay as setImageDelay(intval(round($delay * 100))) (src/Drivers/Imagick/Frame.php:125) — input is seconds, ImageMagick keeps ticks of 1/100s. The message text 'Failed to set frame disposal method' is a copy/paste mistake in the library (the same message exists on setDisposalMethod at line 166): the failure actually concerns the delay. The wrapped ImagickException means an invalid delay value or an unusable native object.
Source
Thrown at src/Drivers/Imagick/Frame.php:127
return $this->native->getImageDelay() / 100;
} catch (ImagickException $e) {
throw new DriverException('Failed to get frame delay', previous: $e);
}
}
/**
* {@inheritdoc}
*
* @see DriverInterface::setDelay()
*
* @throws DriverException
*/
public function setDelay(float $delay): FrameInterface
{
try {
$this->native->setImageDelay(intval(round($delay * 100)));
} catch (ImagickException $e) {
throw new DriverException('Failed to set frame disposal method', previous: $e);
}
return $this;
}
/**
* {@inheritdoc}
*
* @see DriverInterface::disposalMethod()
*
* @throws DriverException
*/
public function disposalMethod(): int
{
try {
return $this->native->getImageDispose();
} catch (ImagickException $e) {
throw new DriverException('Failed to get frame disposal method', previous: $e);View on GitHub (pinned to 5598b9e397)
Solutions
- Clamp the delay before setting: $frame->setDelay(max(0.01, $delay))
- Pass the delay in seconds (0.04 for 25 fps), not in ticks or milliseconds
- Confirm via stack trace that setDelay() threw — the message misleadingly names the disposal method
- Do not reuse frames whose native was cleared; re-read the source image
Example fix
// before $frame->setDelay($newDelay); // may be negative or huge // after $frame->setDelay(max(0.01, min(655.35, $newDelay)));
Defensive patterns
Strategy: validation
Validate before calling
// setDelay() takes SECONDS; clamp to a sane positive range before calling
$delay = max(0.01, min(655.35, (float) $delay));
if (!is_finite($delay)) {
throw new InvalidArgumentException('Delay must be a finite number of seconds');
}
$frame->setDelay($delay); Type guard
function isValidFrameDelay(mixed $delay): bool
{
return is_float($delay) || is_int($delay)
? $delay >= 0 && $delay <= 655.35
: false;
} Try / catch
use Intervention\Image\Exceptions\DriverException;
try {
$frame->setDelay($normalized);
} catch (DriverException $e) {
// message says 'disposal method' but this path is setDelay(); check the trace
if (str_ends_with($e->getTrace()[0]['function'] ?? '', 'setDelay')) {
$frame->setDelay(0.1); // safe default
} else {
throw $e;
}
} Prevention
- Remember the unit contract: seconds in, ticks (1/100s) stored
- Clamp computed delays (from user input or frame diffs) to [0.01, 655.35]
- Do not call setDelay() on frames whose native was cleared; re-read the source
When it happens
Trigger: Setting a negative delay (setDelay(-0.5) maps to setImageDelay(-50)) or a value that overflows the tick range; calling setDelay() on a frame whose native Imagick was cleared/destroyed.
Common situations: Computing delays from user input or frame-diff math without clamping; loops that normalize frame speeds and accidentally produce zero/negative values; reusing frames after teardown of the core.
Related errors
- Failed to get frame delay
- Failed to add image frame
- Failed to iterate image frames
- Failed to load image frame a position
- Frame #
AI-assisted analysis of Intervention/image@5598b9e397 (2026-08-23).
Data as JSON: /api/errors/8140f141564abdfd.
Report an issue: GitHub.