Intervention/image · error · AnalyzerException

Failed to read image resolution

Error message

Failed to read image resolution

What it means

ResolutionAnalyzer::analyze() calls imageresolution() on the image's native GdImage and expects an array [x, y]. If GD returns something else, the analyzer cannot trust any resolution data and throws. In practice imageresolution() only fails this way when the underlying GdImage handle is invalid (already destroyed, or corrupted/replaced from outside the library).

Source

Thrown at src/Drivers/Gd/Analyzers/ResolutionAnalyzer.php:36

class ResolutionAnalyzer extends GenericResolutionAnalyzer implements SpecializedInterface
{
    use CanBuildStream;

    /**
     * {@inheritdoc}
     *
     * @see AnalyzerInterface::analyze()
     *
     * @throws InvalidArgumentException
     * @throws AnalyzerException
     */
    public function analyze(ImageInterface $image): mixed
    {
        $result = imageresolution($image->core()->native());

        if (!is_array($result)) {
            throw new AnalyzerException('Failed to read image resolution');
        }

        // GD returns 96x96 as resolution by default even if the image has no resolution.
        // This is problematic because it is impossible to tell whether the image
        // really has this resolution or whether it just corresponds to the default value.
        //
        // If GD's default resolution is returned here and the resolution is still unchanged
        // we will make an attempt to find the resolution from origin.
        if ($this->isGdDefaultResolution($result) && $image->core()->meta()->get('resolutionChanged') !== true) {
            try {
                $alternativeResoltion = $this->readResolutionFromOrigin($image->origin());
            } catch (Throwable) {
                $alternativeResoltion = [96, 96];
            }

            $result = $alternativeResoltion !== $result ? $alternativeResoltion : $result;
        }

View on GitHub (pinned to 5598b9e397)

Solutions

  1. Remove any imagedestroy() calls on GdImage resources you handed to Intervention Image; the library manages lifecycle itself
  2. Never inject foreign resources via $image->core()->setNative(); create images through ImageManager only
  3. Re-create the image from its origin (read it again) and call resolution() on the fresh object
  4. Check gettype($image->core()->native()) === 'object' && $image->core()->native() instanceof GdImage before probing internals in debug builds

Example fix

// before
$gd = $image->core()->native();
// ... later
imagedestroy($gd);
$resolution = $image->resolution(); // AnalyzerException

// after
$resolution = $image->resolution(); // no manual destroy; let PHP GC handle it
Defensive patterns

Strategy: try-catch

Validate before calling

$native = $image->core()->native();
$usable = $native instanceof GdImage && @imageresolution($native) !== false;

Type guard

function hasValidGdHandle(object $core): bool
{
    $native = $core->native();

    return $native instanceof GdImage;
}

Try / catch

use Intervention\Image\Exceptions\AnalyzerException;

try {
    $resolution = $image->resolution();
} catch (AnalyzerException $e) {
    $image = $manager->read($originPath); // rebuild native and retry
    $resolution = $image->resolution();
}

Prevention

When it happens

Trigger: Calling $image->resolution() after the native GdImage was destroyed with imagedestroy() by external code holding the same resource; swapping $image->core()->setNative(...) with a non-GdImage or already-freed handle and then reading resolution.

Common situations: Integrations that mix legacy GD code (imagedestroy for cleanup) with Intervention Image v3 objects; long-running workers that keep image objects alive past the lifetime of their native resources.

Related errors


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