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

Invalid hsv() or hsb() color syntax "{input}"

Error message

Invalid hsv() or hsb() color syntax "{input}"

What it means

The HSV/HSB string decoder received a string that starts with 'hsv' or 'hsb' but does not match the single supported syntax: hsv(H S V) or hsb(H, S, V) where hue is a plain number (optional 'deg'), saturation and value are numbers with optional '%', and an optional alpha ('/ 0.5', ', 50%', ' 0.5') may follow (PATTERN in src/Colors/Hsv/Decoders/StringColorDecoder.php:18-25). Anything else fails the regex and throws InvalidArgumentException.

Source

Thrown at src/Colors/Hsv/Decoders/StringColorDecoder.php:53

            return false;
        }

        if (preg_match('/^hs(v|b)/i', $input) !== 1) {
            return false;
        }

        return true;
    }

    /**
     * Decode hsv/hsb color strings.
     *
     * @throws InvalidArgumentException
     */
    public function decode(mixed $input): ColorInterface
    {
        if (preg_match(self::PATTERN, $input, $matches) !== 1) {
            throw new InvalidArgumentException('Invalid hsv() or hsb() color syntax "' . $input . '"');
        }

        $values = array_map(fn(string $value): int => match (strpos($value, '%')) {
            false => intval(trim($value)),
            default => intval(trim(str_replace('%', '', $value))),
        }, [$matches['h'], $matches['s'], $matches['v']]);

        // alpha value
        if (array_key_exists('a', $matches)) {
            $values[] = match (strpos($matches['a'], '%')) {
                false => floatval(trim($matches['a'])),
                default => floatval(trim(str_replace('%', '', $matches['a']))) / 100,
            };
        }

        return new Color(...$values);
    }
}

View on GitHub (pinned to 5598b9e397)

Solutions

  1. Rewrite the string to the supported format: comma or single-space separated, e.g. 'hsv(120, 50%, 50%)' or 'hsv(120deg 50% 50% / 0.5)'
  2. Remove unsupported tokens: 'none', negative numbers, extra units
  3. If the input is dynamic, pre-validate with a regex mirroring the supported syntax before handing it to the library
  4. For programmatic values, build the color directly with Hsv\Color::create(h, s, v, alpha) instead of parsing a string

Example fix

// before
$color = Hsv\Color::parse('hsv(120; 50%; 50%)'); // Invalid hsv() or hsb() color syntax

// after
$color = Hsv\Color::parse('hsv(120, 50%, 50%)');
// or without string parsing:
$color = Hsv\Color::create(120, 50, 50);
Defensive patterns

Strategy: validation

Validate before calling

$ok = is_string($input)
    && (bool) preg_match('/^hs(v|b) ?\( ?[0-9.]+(?:deg)?([, ])[0-9.]+%?\\1[0-9.]+%?(?: ?\/ ?|[, ])(?:0?\\.[0-9]+|[0-9]{1,3}%|1|0)? ?\)$/i', $input);
// or simply wrap the risky parse and inspect the message

Type guard

function isHsvString(mixed $input): bool
{
    return is_string($input) && (bool) preg_match('/^hs(v|b) ?\(/i', $input);
}

Try / catch

try {
    $color = Hsv\Color::parse($input);
} catch (Intervention\Image\Exceptions\InvalidArgumentException $e) {
    // normalize $input (e.g. fix separators) and retry, or reject the input
}

Prevention

When it happens

Trigger: Passing strings like 'hsv(120; 50%; 50%)' (semicolon separator), 'hsv(-10, 50%, 50%)' (negative hue), 'hsv(none, 0%, 0%)' (CSS 'none' keyword), 'hsv(120, 50%)' (missing value), or 'hsv(120, 50%, 50%, )' (trailing comma) to Hsv\Color::parse(), a manager color input, or fill()/backgroundColor() options.

Common situations: CSS color strings copied from design tools or CSS4 specs that use syntax variants the library does not support; user input not sanitized before being handed to the color parser; separators or units assumed more permissive than they are.

Related errors


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