{"record":{"id":"5f9c6190b6fa103f","repo":"Intervention/image","slug":"hex-color-has-an-incorrect-length","errorCode":null,"errorMessage":"Hex color has an incorrect length","messagePattern":"Hex color has an incorrect length","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"warning","filePath":"src/Colors/Rgb/Decoders/HexColorDecoder.php","lineNumber":60,"sourceCode":"    }\n\n    /**\n     * Decode hexadecimal rgb colors with and without transparency.\n     *\n     * @throws InvalidArgumentException\n     * @throws ColorDecoderException\n     */\n    public function decode(mixed $input): ColorInterface\n    {\n        if (preg_match(static::PATTERN, $input, $matches) !== 1) {\n            throw new InvalidArgumentException('Hex color has an invalid format');\n        }\n\n        // split into hex chunks\n        $values = match (strlen($matches['hex'])) {\n            3, 4 => str_split($matches['hex']),\n            6, 8 => str_split($matches['hex'], 2),\n            default => throw new InvalidArgumentException('Hex color has an incorrect length'),\n        };\n\n        // convert to decimal\n        $values = array_map(function (string $value): int {\n            return match (strlen($value)) {\n                1 => (int) hexdec($value . $value),\n                2 => (int) hexdec($value),\n                default => throw new ColorDecoderException('Failed to decode hex color'),\n            };\n        }, $values);\n\n        // normalize\n        $values = count($values) === 3 ? array_pad($values, 4, 255) : $values;\n        $values = array_map(fn(int $value): float => $value / 255, $values);\n\n        return Rgb::colorFromNormalized($values);\n    }\n}","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/Intervention/image/blob/5598b9e39751c34afc5cdee84abef77f92c26f68/src/Colors/Rgb/Decoders/HexColorDecoder.php#L42-L78","documentation":"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).","triggerScenarios":"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.","commonSituations":"Extending HexColorDecoder to accept additional hex notations (e.g. 5-digit forms) without updating the length handling; forks adjusting the regex during experimentation.","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"],"exampleFix":"// before\nclass MyHexDecoder extends HexColorDecoder {\n    protected const string PATTERN = '/^#?(?P<hex>[a-f\\d]+)$/i'; // allows any length\n}\n\n// after\nclass MyHexDecoder extends HexColorDecoder {\n    protected const string PATTERN = '/^#?(?P<hex>[a-f\\d]{6})$/i'; // 6 digits only\n}","handlingStrategy":"validation","validationCode":"if (!in_array(strlen(ltrim($hex, '#')), [3, 4, 6, 8], true)) {\n    throw new \\RuntimeException('Hex color length must be 3, 4, 6 or 8 digits');\n}\n$color = \\Intervention\\Image\\Colors\\Rgb\\Color::parse($hex);","typeGuard":"function hasValidHexLength(string $hex): bool\n{\n    return in_array(strlen(ltrim($hex, '#')), [3, 4, 6, 8], true);\n}","tryCatchPattern":"try {\n    $decoder = new \\Intervention\\Image\\Colors\\Rgb\\Decoders\\HexColorDecoder();\n    $color = $decoder->decode($hex);\n} catch (\\Intervention\\Image\\Exceptions\\InvalidArgumentException $e) {\n    $hex = str_pad(ltrim($hex, '#'), 6, '0'); // normalize to 6 digits and retry\n    $color = $decoder->decode($hex);\n}","preventionTips":["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"],"tags":["hex-color","rgb","decoder","php"],"backgroundTag":"invalid-hex-color","analyzedSha":"5598b9e39751c34afc5cdee84abef77f92c26f68","analyzedAt":"2026-08-23T02:17:31.068Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}