Intervention/image · error · Intervention\Image\Exceptions\StateException

Invalid target size

Error message

Invalid target size

What it means

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.

Source

Thrown at src/Geometry/Tools/Resizer.php:91

    {
        return $this->hasTargetHeight() ? $this->height : null;
    }

    /**
     * Return target size object.
     *
     * @throws StateException
     */
    protected function targetSize(): SizeInterface
    {
        if (!$this->hasTargetWidth() || !$this->hasTargetHeight()) {
            throw new StateException('Target size needs width and height');
        }

        try {
            return new Size($this->width, $this->height);
        } catch (InvalidArgumentException $e) {
            throw new StateException('Invalid target size', previous: $e);
        }
    }

    /**
     * Set target width of resizer.
     */
    public function toWidth(int $width): self
    {
        $this->width = $width;

        return $this;
    }

    /**
     * Set target height of resizer.
     */
    public function toHeight(int $height): self
    {

View on GitHub (pinned to 5598b9e397)

Solutions

  1. Inspect getPrevious() to see which dimension and value Size rejected
  2. Validate before calling toWidth()/toHeight() — the setters do not validate: if ($w < 0) { throw ... } or clamp with max(0, $w)
  3. Audit arithmetic that computes target dimensions (padding/margin subtraction is a common source of negatives)
  4. Set dimensions through Resizer::to()/the constructor where possible, which validates immediately

Example fix

// before
$resizer->toWidth($targetWidth - 2 * $padding)->toHeight($h); // negative when target < padding

// after
$resizer->toWidth(max(0, $targetWidth - 2 * $padding))->toHeight($h);
Defensive patterns

Strategy: validation

Validate before calling

$width = max(0, $targetWidth - 2 * $padding);
$resizer = Resizer::to(300, 200)->toWidth($width); // setter does not validate — clamp first

Type guard

function isNonNegativeDimension(int $value): bool
{
    return $value >= 0;
}

Try / catch

try {
    $resizer->cover($sourceSize);
} catch (StateException $e) {
    $cause = $e->getPrevious(); // original InvalidArgumentException names the bad dimension
}

Prevention

When it happens

Trigger: $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().

Common situations: 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.

Related errors


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