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

Unable to import color {color_class} to {colorspace_class}

Error message

Unable to import color {color_class} to {colorspace_class}

What it means

Hsv\Colorspace::importColor() matches the concrete class of the incoming color against the supported built-ins (HsvColor, HslColor, RgbColor, NamedColor, OklabColor, OklchColor) and throws this ColorException ('Unable to import color X to Y') for anything else. It is a supported-type rejection: no conversion is even attempted for unrecognized ColorInterface implementations.

Source

Thrown at src/Colors/Hsv/Colorspace.php:86

    /**
     * {@inheritdoc}
     *
     * @see ColorspaceInterface::importColor()
     *
     * @throws InvalidArgumentException
     * @throws ColorException
     */
    public function importColor(ColorInterface $color): HsvColor
    {
        return match ($color::class) {
            CmykColor::class,
            OklchColor::class,
            NamedColor::class,
            OklabColor::class => $this->importViaRgbColor($color),
            RgbColor::class => $this->importRgbColor($color),
            HslColor::class => $this->importHslColor($color),
            HsvColor::class => $color,
            default => throw new ColorException(
                'Unable to import color ' . $color::class . ' to ' . $this::class,
            ),
        };
    }

    /**
     * Import given RGB color to HSV colorspace.
     *
     * @throws ColorException
     */
    private function importRgbColor(RgbColor $color): HsvColor
    {
        // normalized values of rgb channels
        $values = array_map(
            fn(ColorChannelInterface $channel): float => $channel->normalized(),
            $color->channels(),
        );

View on GitHub (pinned to 5598b9e397)

Solutions

  1. Convert to a built-in first: turn your custom color into an RgbColor, then ->toColorspace(Hsv\Colorspace::class)
  2. Unwrap decorators and import the underlying built-in color instance
  3. Extend a supported class (e.g. Hsv\Color or Rgb\Color) so the match arm recognizes your type
  4. Handle your custom type in your own code and construct Hsv\Color::create(...) directly

Example fix

// before
$hsv = $customColor->toColorspace(Hsv\Colorspace::class); // custom class, no match arm

// after
$rgb = new RgbColor(...$customColor->rgbComponents()); // built-in color
$hsv = $rgb->toColorspace(Hsv\Colorspace::class);
Defensive patterns

Strategy: type-guard

Validate before calling

$supported = [HsvColor::class, HslColor::class, RgbColor::class, NamedColor::class, OklabColor::class, OklchColor::class];
if (!in_array(get_class($color), $supported, true)) {
    $color = $color->toColorspace(Rgb\Colorspace::class); // normalize to a built-in
}

Type guard

function isHsvImportable(ColorInterface $color): bool
{
    return $color instanceof HsvColor
        || $color instanceof HslColor
        || $color instanceof RgbColor
        || $color instanceof NamedColor
        || $color instanceof OklabColor
        || $color instanceof OklchColor;
}

Try / catch

use Intervention\Image\Exceptions\ColorException;

try {
    $hsv = $color->toColorspace(Hsv\Colorspace::class);
} catch (ColorException $e) {
    // unsupported source class; convert manually or reject
}

Prevention

When it happens

Trigger: $color->toColorspace(Hsv\Colorspace::class) where $color is a custom class implementing ColorInterface directly (an adapter, decorator, or DTO) instead of extending one of the built-in color classes.

Common situations: Wrapper colors for caching/serialization/ORM embedding; migration code from other color libraries; test doubles implementing the interface; subclasses of AbstractColor that are not one of the six matched classes.

Related errors


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