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

Failed to invert color

Error message

Failed to invert color

What it means

Final ColorizeModifier range check: blue must be an int in -100..100. Reaching it means red and green are already valid and only blue is out of range. All three guards exist so the exception names the exact offending argument.

Source

Thrown at src/Colors/AbstractColor.php:167

        $hsl = clone $this->toColorspace(HslColorspace::class);
        $hsl->channel(Saturation::class)->scale($level);

        return $hsl->toColorspace($this->colorspace());
    }

    /**
     * {@inheritdoc}
     *
     * @see ColorInterface::withInversion()
     *
     * @throws ColorException
     */
    public function withInversion(): ColorInterface
    {
        try {
            $rgb = $this->toColorspace(RgbColorspace::class);
        } catch (InvalidArgumentException) {
            throw new ColorException('Failed to invert color');
        }

        try {
            $inverted = new \Intervention\Image\Colors\Rgb\Color(
                255 - $rgb->channel(Red::class)->value(),
                255 - $rgb->channel(Green::class)->value(),
                255 - $rgb->channel(Blue::class)->value(),
                $rgb->alpha()->normalized(),
            );
            return $inverted->toColorspace($this->colorspace());
        } catch (InvalidArgumentException) {
            throw new ColorException('Failed to invert color');
        }
    }

    public function jsonSerialize(): mixed
    {
        return $this->toString();

View on GitHub (pinned to 5598b9e397)

Solutions

  1. Clamp blue (and ideally all channels) with max(-100, min(100, $b)).
  2. Validate preset files on load against a -100..100 schema instead of trusting stored numbers.
  3. Audit all call sites once: the same clamp must cover red and green too.

Example fix

// before
$image->colorize(0, 0, $preset['blue']); // -101 throws

// after
$clamp = fn (int $v): int => max(-100, min(100, $v));
$image->colorize($clamp(0), $clamp(0), $clamp($preset['blue']));
Defensive patterns

Strategy: validation

Validate before calling

$clamp = fn (int $v): int => max(-100, min(100, $v));
$image->colorize($clamp($r), $clamp($g), $clamp($b));

Prevention

When it happens

Trigger: $image->colorize(0, 0, -101); only the blue channel coming from a different, unvalidated source (e.g. a preset file).

Common situations: Preset/recipe files (JSON/YAML) with historical values outside the range after a version tightened validation; copy-pasted snippets with extreme blue shifts like -150 for 'sepia-like' effects.

Related errors


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