ramsey/uuid · error · InvalidArgumentException

Value must be a hexadecimal number

Error message

Value must be a hexadecimal number

What it means

Ramsey\Uuid\Type\Hexadecimal is the value object for hexadecimal numbers (used by Uuid::fromHexadecimal() and node/field accessors). prepareValue() lowercases the input, strips an optional leading '0x', and then requires the remainder to match /^[A-Fa-f0-9]+$/ — a non-empty run of hex digits. Anything else, including an empty string or a bare '0x', throws Ramsey\Uuid\Exception\InvalidArgumentException.

Source

Thrown at src/Type/Hexadecimal.php:125

        }
        // @codeCoverageIgnoreEnd

        $this->unserialize($data['string']);
    }

    /**
     * @return non-empty-string
     */
    private function prepareValue(string $value): string
    {
        $value = strtolower($value);

        if (str_starts_with($value, '0x')) {
            $value = substr($value, 2);
        }

        if (!preg_match('/^[A-Fa-f0-9]+$/', $value)) {
            throw new InvalidArgumentException('Value must be a hexadecimal number');
        }

        /** @var non-empty-string */
        return $value;
    }
}

View on GitHub (pinned to da5b521600)

Solutions

  1. Strip non-hex decorations before constructing: ltrim($value, '#') and remove whitespace
  2. Validate before construction: after removing an optional '0x', check $value !== '' && ctype_xdigit($value)
  3. Normalize input to lowercase hex digits only — the class lowercases anyway
  4. Default empty inputs to a meaningful value or reject them at the API boundary

Example fix

// before
$hex = new Hexadecimal('#ff6600');
// InvalidArgumentException: Value must be a hexadecimal number

// after: strip decorations and validate
$raw = strtolower(ltrim($input, '#'));
if ($raw === '' || !ctype_xdigit($raw)) {
    throw new \InvalidArgumentException('Expected a hexadecimal number');
}
$hex = new Hexadecimal($raw); // 'ff6600'
Defensive patterns

Strategy: validation

Validate before calling

// Run before constructing Hexadecimal
$raw = strtolower(trim((string) $value));
$raw = preg_replace('/^0x/', '', $raw) ?? '';
$raw = ltrim($raw, '#');
if ($raw === '' || !ctype_xdigit($raw)) {
    throw new \InvalidArgumentException('Expected a hexadecimal number, got: ' . $value);
}

Type guard

function isHexadecimalString(string $value): bool
{
    $value = preg_replace('/^0x/i', '', $value) ?? '';
    return $value !== '' && ctype_xdigit($value);
}

Try / catch

use Ramsey\Uuid\Exception\InvalidArgumentException;

try {
    $hex = new Hexadecimal($input);
} catch (InvalidArgumentException $e) {
    throw new \InvalidArgumentException('hex field must contain only hex digits', 0, $e);
}

Prevention

When it happens

Trigger: Constructing new Hexadecimal('#ff6600') (CSS-style hash), new Hexadecimal(''), new Hexadecimal('0x') (prefix only), new Hexadecimal('g123'), or a string containing whitespace like 'a1b2 c3'. Also user-supplied hex input from forms or APIs passed through unvalidated.

Common situations: Color codes copied from CSS; concatenating an optional '0x' prefix onto an empty variable; substr() operations that leave an empty string; copy/paste of hex with a '#' or spaces; feeds from external systems using different hex notations.

Related errors


AI-assisted analysis of ramsey/uuid@da5b521600 (2026-08-21). Data as JSON: /api/errors/5d80b24ec13f64e8. Report an issue: GitHub.