{"record":{"id":"cab00f3721124e7a","repo":"Intervention/image","slug":"failed-to-normalize-background-color-to-rgb-color-cab00f","errorCode":null,"errorMessage":"Failed to normalize background color to RGB color space","messagePattern":"Failed to normalize background color to RGB color space","errorType":"exception","errorClass":"ModifierException","httpStatus":null,"severity":"error","filePath":"src/Drivers/Gd/Modifiers/ContainModifier.php","lineNumber":39,"sourceCode":"{\n    /**\n     * {@inheritdoc}\n     *\n     * @see ModifierInterface::apply()\n     *\n     * @throws InvalidArgumentException\n     * @throws ModifierException\n     * @throws StateException\n     * @throws DriverException\n     */\n    public function apply(ImageInterface $image): ImageInterface\n    {\n        $crop = $this->cropSize($image);\n        $resize = $this->resizeSize($image);\n        $backgroundColor = $this->backgroundColor()->toColorspace(Rgb::class);\n\n        if (!$backgroundColor instanceof RgbColor) {\n            throw new ModifierException('Failed to normalize background color to RGB color space');\n        }\n\n        foreach ($image as $frame) {\n            $this->modify($frame, $crop, $resize, $backgroundColor);\n        }\n\n        return $image;\n    }\n\n    /**\n     * @throws InvalidArgumentException\n     * @throws ModifierException\n     * @throws DriverException\n     */\n    private function modify(\n        FrameInterface $frame,\n        SizeInterface $crop,\n        SizeInterface $resize,","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/Intervention/image/blob/5598b9e39751c34afc5cdee84abef77f92c26f68/src/Drivers/Gd/Modifiers/ContainModifier.php#L21-L57","documentation":"Thrown by the GD driver's contain() implementation. Contain resizing letterboxes the image into the target box and fills the newly created areas with a background color, and GD needs a concrete RGB color for that. The modifier converts the configured background via ColorInterface::toColorspace(Rgb\\Colorspace::class) and asserts the result is an Intervention\\Image\\Colors\\Rgb\\Color. Every color the library decodes itself (hex strings, rgb()/rgba(), named colors, built-in colorspace objects) converts into an Rgb\\Color, so with standard input values this exception is effectively unreachable.","triggerScenarios":"Calling $image->contain($w, $h, $background) where $background is a custom ColorInterface implementation whose toColorspace(Rgb\\Colorspace::class) does not return Rgb\\Color; running contain() without an explicit background while a custom Config->backgroundColor object of that kind is set; custom color decoders registered into the driver's decodeColor() pipeline returning non-standard color objects.","commonSituations":"Extending Intervention Image with your own color/colorspace classes; passing color objects received from another package into the background parameter; upgrading across versions where the internal colorspace import API (importColor()) changed; copying Imagick-driver code that used Imagick-specific color objects into a GD pipeline.","solutions":["Pass a standard color value instead: a hex string like '#ff0000', 'rgb(255, 0, 0)', a named color, or an instance of Intervention\\Image\\Colors\\Rgb\\Color","If you control the custom color class, make its toColorspace(Rgb\\Colorspace::class) return an Intervention\\Image\\Colors\\Rgb\\Color","Convert the color yourself before passing it: $custom->toColorspace(Intervention\\Image\\Colors\\Rgb\\Colorspace::class)","Wrap the call in a try/catch on Intervention\\Image\\Exceptions\\ModifierException and retry with a safe fallback color"],"exampleFix":"// before: custom color object that does not convert to Rgb\\Color\n$image->contain(1200, 630, $customColorObject);\n\n// after: pass an RGB value the GD driver can always use\nuse Intervention\\Image\\Colors\\Rgb\\Color;\n$image->contain(1200, 630, new Color(255, 0, 0));","handlingStrategy":"type-guard","validationCode":"use Intervention\\Image\\Colors\\Rgb\\Color as RgbColor;\nuse Intervention\\Image\\Colors\\Rgb\\Colorspace as RgbColorspace;\nuse Intervention\\Image\\Interfaces\\ColorInterface;\n\n// normalize anything color-like into an Rgb\\Color before calling contain()\n$background = $color instanceof ColorInterface\n    ? $color->toColorspace(RgbColorspace::class)\n    : $color; // strings are always decodable by the driver\n\nif (!$background instanceof RgbColor) {\n    throw new LogicException('Background color does not convert to Rgb\\Color');\n}\n\n$image->contain(1200, 630, $background);","typeGuard":"use Intervention\\Image\\Colors\\Rgb\\Color as RgbColor;\nuse Intervention\\Image\\Colors\\Rgb\\Colorspace as RgbColorspace;\nuse Intervention\\Image\\Interfaces\\ColorInterface;\n\nfunction isGdSafeBackground(string|ColorInterface $color): bool\n{\n    return is_string($color)\n        || $color->toColorspace(RgbColorspace::class) instanceof RgbColor;\n}","tryCatchPattern":"use Intervention\\Image\\Exceptions\\ModifierException;\n\ntry {\n    $image->contain(1200, 630, $background);\n} catch (ModifierException $e) {\n    // degrade gracefully with a known-good color\n    $image->contain(1200, 630, 'ffffff');\n}","preventionTips":["Prefer hex/rgb strings or Rgb\\Color instances for background parameters when using the GD driver.","If you extend the color system, add a unit test asserting toColorspace(Rgb\\Colorspace::class) instanceof Rgb\\Color.","Keep custom colors out of Config->backgroundColor unless they pass the same conversion test."],"tags":["gd","contain","resize","background-color","colorspace","rgb"],"backgroundTag":"colorspace-conversion-failed","analyzedSha":"5598b9e39751c34afc5cdee84abef77f92c26f68","analyzedAt":"2026-08-23T02:17:31.068Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}