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

  1. Clamp the delay before setting: $frame->setDelay(max(0.01, $delay))
  2. Pass the delay in seconds (0.04 for 25 fps), not in ticks or milliseconds
  3. Confirm via stack trace that setDelay() threw — the message misleadingly names the disposal method
  4. 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

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


AI-assisted analysis of Intervention/image@5598b9e397 (2026-08-23). Data as JSON: /api/errors/8140f141564abdfd. Report an issue: GitHub.