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
- Clamp blue (and ideally all channels) with max(-100, min(100, $b)).
- Validate preset files on load against a -100..100 schema instead of trusting stored numbers.
- 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
- Validate stored presets/recipes against a -100..100 schema on load.
- Apply the same clamp to values read from config files.
- Cover all three channels in tests at the boundaries (-100, 0, 100).
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
- Color channel {class} value must be in range {min} to {max}
- Unable to parse CMYK color from input "{input}"
- Percentage value must be between -100 and 100
- Color channel value of {class} must be in range 0 to 1
- Number of color channels must be 4 or 5 for {class}
AI-assisted analysis of Intervention/image@5598b9e397 (2026-08-23).
Data as JSON: /api/errors/b64aafe0e4d519d3.
Report an issue: GitHub.