Intervention/image · error · Intervention\Image\Exceptions\InvalidArgumentException
Image source must be an instance of Imagick
Error message
Image source must be an instance of Imagick
What it means
NativeObjectDecoder::decode() was called with a value that is not an Imagick object. In normal usage ImageManager::read() routes input through the decoder chain via supports() (which checks instanceof Imagick), so hitting this means the specialized decoder was invoked directly or a custom pipeline bypassed the manager's routing.
Source
Thrown at src/Drivers/Imagick/Decoders/NativeObjectDecoder.php:46
public function supports(mixed $input): bool
{
return $input instanceof Imagick;
}
/**
* {@inheritdoc}
*
* @see DecoderInterface::decode()
*
* @throws InvalidArgumentException
* @throws StateException
* @throws DriverException
* @throws ImageDecoderException
*/
public function decode(mixed $input): ImageInterface
{
if (!$input instanceof Imagick) {
throw new InvalidArgumentException('Image source must be an instance of Imagick');
}
try {
$originalMimeType = $input->getImageMimeType();
} catch (ImagickException $e) {
throw new ImageDecoderException('Failed to retrieve image media type', previous: $e);
}
// For some JPEG formats, the "coalesceImages()" call leads to an image
// completely filled with background color. The logic behind this is
// incomprehensible for me; could be an imagick bug.
try {
if ($input->getImageFormat() !== 'JPEG') {
$input = $input->coalesceImages();
}
} catch (ImagickException $e) {
throw new DriverException('Failed to coalesce image', previous: $e);
}View on GitHub (pinned to 5598b9e397)
Solutions
- Use ImageManager::read($input) instead of calling the decoder directly - it routes Imagick objects to this decoder automatically
- If calling decode() directly, guard with instanceof Imagick or the decoder's supports() method first
- For GD-native objects (GdImage), construct the manager with the GD driver and read through it
Example fix
// before $decoder = new NativeObjectDecoder($driver); $image = $decoder->decode($gdImage); // GdImage passed to Imagick decoder // after: route through the manager, which dispatches by type via supports() $gdManager = new ImageManager(['driver' => 'gd']); $image = $gdManager->read($gdImage); // or for Imagick: $manager->read($imagick)
Defensive patterns
Strategy: type-guard
Type guard
function isImagickObject(mixed $value): bool
{
return $value instanceof \Imagick;
} Prevention
- Route native objects through ImageManager::read() so supports() picks the right decoder
- Never call a specialized decoder directly without an instanceof check matching its supports()
When it happens
Trigger: Calling (new NativeObjectDecoder($driver))->decode($value) manually with a GdImage, ImagickPixel, string or null; custom decoder chains assembled by hand; code ported from the GD driver where the native object type is GdImage.
Common situations: Porting driver-specific code from GD to Imagick; wrapper classes that hold a 'native' object of mixed driver origin and pass it to the wrong decoder.
Understand the failure class
Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.
Related errors
- Image source must be binary data of type string or instance
- Image source must be data uri scheme of type string or Inter
- Image source must be of type Intervention\Image\EncodedImage
- Image source must be of type GdImage
- Image source must be of type SplFileInfo
AI-assisted analysis of Intervention/image@5598b9e397 (2026-08-23).
Data as JSON: /api/errors/660d6865b9b080cc.
Report an issue: GitHub.