{"record":{"id":"aff7bd2e2c946609","repo":"Intervention/image","slug":"failed-to-read-image-resolution","errorCode":null,"errorMessage":"Failed to read image resolution","messagePattern":"Failed to read image resolution","errorType":"exception","errorClass":"AnalyzerException","httpStatus":null,"severity":"error","filePath":"src/Drivers/Gd/Analyzers/ResolutionAnalyzer.php","lineNumber":36,"sourceCode":"\nclass ResolutionAnalyzer extends GenericResolutionAnalyzer implements SpecializedInterface\n{\n    use CanBuildStream;\n\n    /**\n     * {@inheritdoc}\n     *\n     * @see AnalyzerInterface::analyze()\n     *\n     * @throws InvalidArgumentException\n     * @throws AnalyzerException\n     */\n    public function analyze(ImageInterface $image): mixed\n    {\n        $result = imageresolution($image->core()->native());\n\n        if (!is_array($result)) {\n            throw new AnalyzerException('Failed to read image resolution');\n        }\n\n        // GD returns 96x96 as resolution by default even if the image has no resolution.\n        // This is problematic because it is impossible to tell whether the image\n        // really has this resolution or whether it just corresponds to the default value.\n        //\n        // If GD's default resolution is returned here and the resolution is still unchanged\n        // we will make an attempt to find the resolution from origin.\n        if ($this->isGdDefaultResolution($result) && $image->core()->meta()->get('resolutionChanged') !== true) {\n            try {\n                $alternativeResoltion = $this->readResolutionFromOrigin($image->origin());\n            } catch (Throwable) {\n                $alternativeResoltion = [96, 96];\n            }\n\n            $result = $alternativeResoltion !== $result ? $alternativeResoltion : $result;\n        }\n","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/Intervention/image/blob/5598b9e39751c34afc5cdee84abef77f92c26f68/src/Drivers/Gd/Analyzers/ResolutionAnalyzer.php#L18-L54","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Remove any imagedestroy() calls on GdImage resources you handed to Intervention Image; the library manages lifecycle itself","Never inject foreign resources via $image->core()->setNative(); create images through ImageManager only","Re-create the image from its origin (read it again) and call resolution() on the fresh object","Check gettype($image->core()->native()) === 'object' && $image->core()->native() instanceof GdImage before probing internals in debug builds"],"exampleFix":"// before\n$gd = $image->core()->native();\n// ... later\nimagedestroy($gd);\n$resolution = $image->resolution(); // AnalyzerException\n\n// after\n$resolution = $image->resolution(); // no manual destroy; let PHP GC handle it","handlingStrategy":"try-catch","validationCode":"$native = $image->core()->native();\n$usable = $native instanceof GdImage && @imageresolution($native) !== false;","typeGuard":"function hasValidGdHandle(object $core): bool\n{\n    $native = $core->native();\n\n    return $native instanceof GdImage;\n}","tryCatchPattern":"use Intervention\\Image\\Exceptions\\AnalyzerException;\n\ntry {\n    $resolution = $image->resolution();\n} catch (AnalyzerException $e) {\n    $image = $manager->read($originPath); // rebuild native and retry\n    $resolution = $image->resolution();\n}","preventionTips":["Never call imagedestroy() on a GdImage you passed into an Intervention Image object","Create and mutate images only through ImageManager and modifier methods","Treat this exception as a signal that native state was corrupted externally"],"tags":["gd","resolution","native-handle","imageresolution"],"backgroundTag":"invalid-image-handle","analyzedSha":"5598b9e39751c34afc5cdee84abef77f92c26f68","analyzedAt":"2026-08-23T02:17:31.068Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}