{"record":{"id":"edbee575ba8a7d7d","repo":"Intervention/image","slug":"invalid-target-size","errorCode":null,"errorMessage":"Invalid target size","messagePattern":"Invalid target size","errorType":"exception","errorClass":"Intervention\\Image\\Exceptions\\StateException","httpStatus":null,"severity":"error","filePath":"src/Geometry/Tools/Resizer.php","lineNumber":91,"sourceCode":"    {\n        return $this->hasTargetHeight() ? $this->height : null;\n    }\n\n    /**\n     * Return target size object.\n     *\n     * @throws StateException\n     */\n    protected function targetSize(): SizeInterface\n    {\n        if (!$this->hasTargetWidth() || !$this->hasTargetHeight()) {\n            throw new StateException('Target size needs width and height');\n        }\n\n        try {\n            return new Size($this->width, $this->height);\n        } catch (InvalidArgumentException $e) {\n            throw new StateException('Invalid target size', previous: $e);\n        }\n    }\n\n    /**\n     * Set target width of resizer.\n     */\n    public function toWidth(int $width): self\n    {\n        $this->width = $width;\n\n        return $this;\n    }\n\n    /**\n     * Set target height of resizer.\n     */\n    public function toHeight(int $height): self\n    {","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/Intervention/image/blob/5598b9e39751c34afc5cdee84abef77f92c26f68/src/Geometry/Tools/Resizer.php#L73-L109","documentation":"targetSize() wraps the construction of a Size object from the resizer's stored width/height; if Size's constructor rejects the values (width or height < 0, see Size.php:36-46), it is rethrown as StateException('Invalid target size') with the original InvalidArgumentException attached as previous. The key subtlety: the Resizer constructor only validates values passed to it — the toWidth()/toHeight() setters (Resizer.php:98-113) assign without any validation, so negative values can slip in there and only explode later at cover/contain time.","triggerScenarios":"$resizer->toWidth(-10)->toHeight(50)->cover(...) — setter-assigned negative dimension passes silently and fails in targetSize(); also toSize() with a custom SizeInterface implementation returning negative width()/height().","commonSituations":"Arithmetic that produces negative dimensions (e.g. subtracting padding from a small target size), sign errors, or custom SizeInterface implementations that are not validated. Distant, hard-to-trace failure because the invalid value was accepted earlier by a setter.","solutions":["Inspect getPrevious() to see which dimension and value Size rejected","Validate before calling toWidth()/toHeight() — the setters do not validate: if ($w < 0) { throw ... } or clamp with max(0, $w)","Audit arithmetic that computes target dimensions (padding/margin subtraction is a common source of negatives)","Set dimensions through Resizer::to()/the constructor where possible, which validates immediately"],"exampleFix":"// before\n$resizer->toWidth($targetWidth - 2 * $padding)->toHeight($h); // negative when target < padding\n\n// after\n$resizer->toWidth(max(0, $targetWidth - 2 * $padding))->toHeight($h);","handlingStrategy":"validation","validationCode":"$width = max(0, $targetWidth - 2 * $padding);\n$resizer = Resizer::to(300, 200)->toWidth($width); // setter does not validate — clamp first","typeGuard":"function isNonNegativeDimension(int $value): bool\n{\n    return $value >= 0;\n}","tryCatchPattern":"try {\n    $resizer->cover($sourceSize);\n} catch (StateException $e) {\n    $cause = $e->getPrevious(); // original InvalidArgumentException names the bad dimension\n}","preventionTips":["Never trust toWidth()/toHeight() to validate — they assign blindly","Clamp computed dimensions to >= 0 before setting them","Prefer the constructor / Resizer::to() which validates immediately"],"tags":["geometry","resizer","state","dimensions","deferred-validation"],"backgroundTag":"invalid-image-dimensions","analyzedSha":"5598b9e39751c34afc5cdee84abef77f92c26f68","analyzedAt":"2026-08-23T02:17:31.068Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}