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
- Validate the variant bits before converting: first byte of the 4th group must be hex 8-b (RFC 9562) or c-d (Microsoft)
- Use Guid::fromString()/fromBytes() on trusted GUID data only, and catch UnableToBuildUuidException when parsing untrusted input
- 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
- Only convert RFC/Microsoft-conformant values into Guid
- Validate variant bits once at your ingestion boundary
- Keep opaque 128-bit identifiers as Hexadecimal, not Guid
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
- The byte string must be 16 bytes long; received {bytes} byte
- The byte string received does not contain a valid version
- The byte string received does not conform to the RFC 9562 (f
- The byte string must be 16 bytes long; received {bytes} byte
- The byte string must be 16 bytes long; received {} bytes
AI-assisted analysis of ramsey/uuid@da5b521600 (2026-08-21).
Data as JSON: /api/errors/ed583e37f07010ea.
Report an issue: GitHub.