Intervention/image · warning · InvalidArgumentException
Hex color has an incorrect length
Error message
Hex color has an incorrect length
What it means
After the structural pattern match, HexColorDecoder::decode() splits the hex portion by length: 3 or 4 digits are split per character, 6 or 8 per pair, and any other length throws this InvalidArgumentException. The built-in pattern can only capture 3, 4, 6 or 8 digits, so through public APIs this branch is defensive and effectively unreachable; it fires only when a subclass overrides the protected PATTERN constant with one that admits 5- or 7-digit groups (NamedColorDecoder extends this class and relies on the same code path).
Source
Thrown at src/Colors/Rgb/Decoders/HexColorDecoder.php:60
}
/**
* 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);
// normalize
$values = count($values) === 3 ? array_pad($values, 4, 255) : $values;
$values = array_map(fn(int $value): float => $value / 255, $values);
return Rgb::colorFromNormalized($values);
}
}View on GitHub (pinned to 5598b9e397)
Solutions
- Keep overridden patterns limited to 3, 4, 6 or 8 captured hex digits
- If you must accept other lengths, override decode() as well and normalize to a supported length first
- Map exotic notations to a canonical 6- or 8-digit hex string before decoding
Example fix
// before
class MyHexDecoder extends HexColorDecoder {
protected const string PATTERN = '/^#?(?P<hex>[a-f\d]+)$/i'; // allows any length
}
// after
class MyHexDecoder extends HexColorDecoder {
protected const string PATTERN = '/^#?(?P<hex>[a-f\d]{6})$/i'; // 6 digits only
} Defensive patterns
Strategy: validation
Validate before calling
if (!in_array(strlen(ltrim($hex, '#')), [3, 4, 6, 8], true)) {
throw new \RuntimeException('Hex color length must be 3, 4, 6 or 8 digits');
}
$color = \Intervention\Image\Colors\Rgb\Color::parse($hex); Type guard
function hasValidHexLength(string $hex): bool
{
return in_array(strlen(ltrim($hex, '#')), [3, 4, 6, 8], true);
} Try / catch
try {
$decoder = new \Intervention\Image\Colors\Rgb\Decoders\HexColorDecoder();
$color = $decoder->decode($hex);
} catch (\Intervention\Image\Exceptions\InvalidArgumentException $e) {
$hex = str_pad(ltrim($hex, '#'), 6, '0'); // normalize to 6 digits and retry
$color = $decoder->decode($hex);
} Prevention
- Unreachable with the stock pattern; only subclasses overriding PATTERN can trigger it
- Keep overridden PATTERN constants limited to 3/4/6/8-digit captures
- Pre-normalize exotic hex notations to 6 or 8 digits before decoding
When it happens
Trigger: A custom subclass of HexColorDecoder overriding PATTERN to capture hex strings whose length is 5 or 7, then calling decode(); direct instantiation is not affected because the stock pattern never yields those lengths.
Common situations: Extending HexColorDecoder to accept additional hex notations (e.g. 5-digit forms) without updating the length handling; forks adjusting the regex during experimentation.
Related errors
- Failed to decode hex color
- Hex color has an invalid format
- Failed to import color {colorClass} to {class}
- Failed to import color {color_class} to {colorspace_class}
- Failed to import color {color_class} to {colorspace_class}
AI-assisted analysis of Intervention/image@5598b9e397 (2026-08-23).
Data as JSON: /api/errors/5f9c6190b6fa103f.
Report an issue: GitHub.