Intervention/image · error · InvalidArgumentException
Hex color has an invalid format
Error message
Hex color has an invalid format
What it means
HexColorDecoder::decode() validates the input against a strict structural pattern: an optional '#' followed by exactly 3, 4, 6 or 8 hex digits. The gatekeeper supports() is much looser (any string starting with '#', or up to 8 chars that are all hex), so strings like '#1' or '#zz' reach decode() and fail the full pattern, throwing this InvalidArgumentException.
Source
Thrown at src/Colors/Rgb/Decoders/HexColorDecoder.php:53
// matching max. length & only hexadecimal
if (strlen($input) <= 8 && preg_match('/^[a-f\d]+$/i', $input) === 1) {
return true;
}
return preg_match(static::PATTERN, $input) === 1;
}
/**
* Decode hexadecimal rgb colors with and without transparency.
*
* @throws InvalidArgumentException
* @throws ColorDecoderException
*/
public function decode(mixed $input): ColorInterface
{
if (preg_match(static::PATTERN, $input, $matches) !== 1) {
throw new InvalidArgumentException('Hex color has an invalid format');
}
// split into hex chunks
$values = match (strlen($matches['hex'])) {
3, 4 => str_split($matches['hex']),
6, 8 => str_split($matches['hex'], 2),
default => throw new InvalidArgumentException('Hex color has an incorrect length'),
};
// convert to decimal
$values = array_map(function (string $value): int {
return match (strlen($value)) {
1 => (int) hexdec($value . $value),
2 => (int) hexdec($value),
default => throw new ColorDecoderException('Failed to decode hex color'),
};
}, $values);
View on GitHub (pinned to 5598b9e397)
Solutions
- Provide a well-formed hex value: #f00, #f00f, #ff0000 or #ff0000ff (3, 4, 6 or 8 hex digits)
- Trim whitespace and validate with your own regex before parsing: preg_match('/^#?([a-f\d]{3}|[a-f\d]{4}|[a-f\d]{6}|[a-f\d]{8})$/i', $input)
- Catch InvalidArgumentException when parsing free-form user input and surface a form error
Example fix
// before
$color = \Intervention\Image\Colors\Rgb\Color::parse('#00ff0g');
// after
$input = trim($request->input('color'));
if (!preg_match('/^#?([a-f\d]{3}|[a-f\d]{4}|[a-f\d]{6}|[a-f\d]{8})$/i', $input)) {
throw new \RuntimeException('Please provide a valid hex color');
}
$color = \Intervention\Image\Colors\Rgb\Color::parse($input); Defensive patterns
Strategy: validation
Validate before calling
$input = trim($input);
if (!preg_match('/^#?([a-f\d]{3}|[a-f\d]{4}|[a-f\d]{6}|[a-f\d]{8})$/i', $input)) {
throw new \RuntimeException('Invalid hex color: ' . $input);
}
$color = \Intervention\Image\Colors\Rgb\Color::parse($input); Type guard
function isHexColorString(mixed $input): bool
{
return is_string($input)
&& preg_match('/^#?([a-f\d]{3}|[a-f\d]{4}|[a-f\d]{6}|[a-f\d]{8})$/i', $input) === 1;
} Try / catch
try {
$color = \Intervention\Image\Colors\Rgb\Color::parse($hex);
} catch (\Intervention\Image\Exceptions\InvalidArgumentException $e) {
// surface a form validation error instead of a 500
$errors['color'] = 'Please use a hex value like #ff0000';
} Prevention
- Validate hex input with your own regex before parsing
- Trim whitespace; only 3, 4, 6 or 8 hex digits (optional '#') are accepted
- Note supports() is loose: any '#...' string reaches decode(), so the exception can fire for near-misses
When it happens
Trigger: Rgb\Color::parse('#zzz'), parse('#1'), parse('f0') (too short), or input containing non-hex characters that still passed the loose supports() check. Also reachable by calling HexColorDecoder::decode() directly.
Common situations: User-typed color values ('#red', '#00ff0g'); truncation bugs cutting hex strings short ('#ff0' is fine, '#f0' is not); whitespace or newlines around the value surviving a trim-less pipeline.
Related errors
- Invalid rgb() color syntax "{input}"
- Unable to parse RGB color from input "{input}"
- Hex color has an incorrect length
- Failed to decode hex color
- Invalid cmyk() color syntax "{input}"
AI-assisted analysis of Intervention/image@5598b9e397 (2026-08-23).
Data as JSON: /api/errors/cab70b9b4315b35d.
Report an issue: GitHub.