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) variant

What it means

Rfc4122\Fields validates the variant bits for standard UUIDs: the top bits of clock_seq_hi_and_reserved (first hex character of the UUID's 4th group) must be 10xx, i.e. 8, 9, a, or b. Nil and max UUIDs bypass the check. Bytes whose variant nibble is 0-7 (NCS/reserved), c-d (Microsoft), or e-f (future reserved) are rejected with InvalidArgumentException. Because UuidBuilder wraps failures, this message usually arrives as the message of an UnableToBuildUuidException.

Source

Thrown at src/Rfc4122/Fields.php:64

    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 an RFC 9562 (formerly RFC 4122) UUID
     * @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) variant',
            );
        }

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

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

View on GitHub (pinned to da5b521600)

Solutions

  1. Validate before parsing: first hex char of the 4th group must be one of 8,9,a,b
  2. Reject at the boundary by catching UnableToBuildUuidException when parsing untrusted UUID strings
  3. Treat Microsoft-variant GUIDs (c/d) as Guid via Guid::fromString(), not Uuid::fromString()

Example fix

// before
$uuid = \Ramsey\Uuid\Uuid::fromString($candidate); // variant nibble invalid

// after
function isRfc4122Variant(string $s): bool
{
    $c = strtolower(preg_replace('/[^0-9a-f]/i', '', $s)[16] ?? '0');
    return in_array($c, ['8', '9', 'a', 'b'], true);
}
$uuid = isRfc4122Variant($candidate)
    ? \Ramsey\Uuid\Uuid::fromString($candidate)
    : throw new InvalidArgumentException('Not an RFC 9562 variant UUID');
Defensive patterns

Strategy: validation

Validate before calling

$hex = strtolower(preg_replace('/[^0-9a-f]/i', '', $candidate));
$variantNibble = $hex[16] ?? '';
if (!in_array($variantNibble, ['8', '9', 'a', 'b'], true)) {
    throw new InvalidArgumentException('Not an RFC 9562 variant UUID');
}
$uuid = \Ramsey\Uuid\Uuid::fromString($candidate);

Type guard

function isRfc4122VariantString(string $uuid): bool
{
    $hex = strtolower(preg_replace('/^urn:uuid:|[^0-9a-f]/i', '', $uuid));
    return strlen($hex) === 32
        && in_array($hex[16], ['8', '9', 'a', 'b'], true);
}

Try / catch

try {
    $uuid = \Ramsey\Uuid\Uuid::fromString($input);
} catch (\Ramsey\Uuid\Exception\UnableToBuildUuidException $e) {
    if (str_contains($e->getMessage(), 'variant')) {
        // variant bits wrong: 4th group must start with 8/9/a/b
    }
}

Prevention

When it happens

Trigger: Uuid::fromString('12345678-1234-4fff-ffff-123456789abc') — the 4th group starts with 'f', so the variant bits are 1111 and parsing throws this error (wrapped by UnableToBuildUuidException). Also direct Rfc4122\Fields construction or custom codecs with non-RFC bytes. Uuid::isValid() passes these strings since it only checks hex format.

Common situations: Parsing log-stripped or hand-typed UUIDs with a typo in the 4th group; accepting IDs from other systems that emit non-RFC variant bits; test fixtures with placeholder hex like all-f; bit-mangling transformations that touch the clock_seq bytes.

Related errors


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