ramsey/uuid · error · InvalidArgumentException

The byte string received does not conform to the RFC 9562 (f

Error message

The byte string received does not conform to the RFC 9562 (formerly RFC 4122) or Microsoft Corporation variants

What it means

When ramsey/uuid builds a Guid from 16 bytes, Guid\Fields validates the variant bits. After the little-endian swap, the top bits of clock_seq_hi_and_reserved (first character of the string's 4th group) must be 10xx (RFC 9562 variant, hex 8-b) or 110x (Microsoft variant, hex c-d); 0xxx (NCS/reserved) and 111x (future reserved) variants are rejected, except for the all-zero nil and all-f max UUIDs which bypass the check.

Source

Thrown at src/Guid/Fields.php:70

    use VersionTrait;

    /**
     * @param string $bytes A 16-byte binary string representation of a UUID
     *
     * @throws InvalidArgumentException if the byte string is not exactly 16 bytes
     * @throws InvalidArgumentException if the byte string does not represent a GUID
     * @throws InvalidArgumentException if the byte string does not contain a valid version
     */
    public function __construct(private string $bytes)
    {
        if (strlen($this->bytes) !== 16) {
            throw new InvalidArgumentException(
                'The byte string must be 16 bytes long; received ' . strlen($this->bytes) . ' bytes',
            );
        }

        if (!$this->isCorrectVariant()) {
            throw new InvalidArgumentException(
                'The byte string received does not conform to the RFC 9562 (formerly RFC 4122) '
                . 'or Microsoft Corporation variants',
            );
        }

        if (!$this->isCorrectVersion()) {
            throw new InvalidArgumentException('The byte string received does not contain a valid version');
        }
    }

    public function getBytes(): string
    {
        return $this->bytes;
    }

    public function getTimeLow(): Hexadecimal
    {
        // Swap the bytes from little endian to network byte order.

View on GitHub (pinned to da5b521600)

Solutions

  1. Validate the variant bits before converting: first byte of the 4th group must be hex 8-b (RFC 9562) or c-d (Microsoft)
  2. Use Guid::fromString()/fromBytes() on trusted GUID data only, and catch UnableToBuildUuidException when parsing untrusted input
  3. If the value is a generic 128-bit identifier, keep it as a Hexadecimal instead of forcing it into a Guid

Example fix

// before
$guid = \Ramsey\Uuid\Guid\Guid::fromBytes($arbitraryBytes);

// after
$variantNibble = hexdec(bin2hex($arbitraryBytes[8])) >> 4;
if ($variantNibble < 0x8 || $variantNibble > 0xd) {
    throw new InvalidArgumentException('Not a GUID-variant value');
}
$guid = \Ramsey\Uuid\Guid\Guid::fromBytes($arbitraryBytes);
Defensive patterns

Strategy: validation

Validate before calling

$nibble = hexdec(bin2hex($bytes[8])) >> 4; // after little-endian context is settled
// RFC 9562: 0x8-0xb, Microsoft: 0xc-0xd
if ($nibble < 0x8 || $nibble > 0xd) {
    throw new InvalidArgumentException('Not a GUID-variant 128-bit value');
}

Type guard

function isGuidVariantBytes(string $bytes): bool
{
    if (strlen($bytes) !== 16) {
        return false;
    }
    $n = hexdec(bin2hex($bytes[8])) >> 4;
    return ($n >= 0x8 && $n <= 0xd)
        || $bytes === str_repeat("\x00", 16)
        || $bytes === str_repeat("\xff", 16);
}

Try / catch

try {
    $guid = \Ramsey\Uuid\Guid\Guid::fromBytes($bytes);
} catch (\Ramsey\Uuid\Exception\UnableToBuildUuidException $e) {
    if (str_contains($e->getMessage(), 'variants')) {
        // value is not a real GUID; treat as opaque 128-bit data
    }
}

Prevention

When it happens

Trigger: Decoding 16 bytes that are not a real GUID: Guid::fromBytes($bytes) or a custom codec where the variant octet starts with hex 0-7, e, or f. Example: Guid::fromBytes(hex2bin(str_repeat('f', 32))) throws this because the variant bits read 1111 (future).

Common situations: Converting arbitrary 16-byte identifiers (hashes, rowids, encryption output) to Guid; corrupted binary from external systems; hand-built test fixtures with random variant bits.

Related errors


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