ramsey/uuid · error · DceSecurityException

Clock sequence out of bounds; it must be a value between 0 a

Error message

Clock sequence out of bounds; it must be a value between 0 and 63

What it means

In DCE Security (version 2) UUIDs the clock sequence field is only 6 bits, so DceSecurityGenerator enforces 0..63 (CLOCK_SEQ_LOW..CLOCK_SEQ_HIGH) and throws DceSecurityException outside that range. This is much narrower than the 14-bit clock sequence of ordinary v1 UUIDs (0..16383).

Source

Thrown at src/Generator/DceSecurityGenerator.php:79

    public function generate(
        int $localDomain,
        ?IntegerObject $localIdentifier = null,
        ?Hexadecimal $node = null,
        ?int $clockSeq = null,
    ): string {
        if (!in_array($localDomain, self::DOMAINS)) {
            throw new DceSecurityException('Local domain must be a valid DCE Security domain');
        }

        if ($localIdentifier && $localIdentifier->isNegative()) {
            throw new DceSecurityException(
                'Local identifier out of bounds; it must be a value between 0 and 4294967295',
            );
        }

        if ($clockSeq > self::CLOCK_SEQ_HIGH || $clockSeq < self::CLOCK_SEQ_LOW) {
            throw new DceSecurityException('Clock sequence out of bounds; it must be a value between 0 and 63');
        }

        switch ($localDomain) {
            case Uuid::DCE_DOMAIN_ORG:
                if ($localIdentifier === null) {
                    throw new DceSecurityException('A local identifier must be provided for the org domain');
                }

                break;
            case Uuid::DCE_DOMAIN_PERSON:
                if ($localIdentifier === null) {
                    $localIdentifier = $this->dceSecurityProvider->getUid();
                }

                break;
            case Uuid::DCE_DOMAIN_GROUP:
            default:
                if ($localIdentifier === null) {

View on GitHub (pinned to da5b521600)

Solutions

  1. Pass null to let the generator pick a value, or constrain to 0..63.
  2. Mask when porting v1-style values: $clockSeq & 0x3f.
  3. Validate configuration constants against the 0..63 range at startup.

Example fix

// before
$uuid = Uuid::uuid2(Uuid::DCE_DOMAIN_PERSON, null, null, 4096); // > 63

// after
$uuid = Uuid::uuid2(Uuid::DCE_DOMAIN_PERSON, null, null, 4096 & 0x3f);
Defensive patterns

Strategy: validation

Validate before calling

if ($clockSeq !== null && ($clockSeq < 0 || $clockSeq > 63)) {
    $clockSeq = $clockSeq & 0x3f; // clamp to the 6-bit v2 field
}
$uuid = Uuid::uuid2($domain, $identifier, $node, $clockSeq);

Type guard

function isValidDceClockSeq(?int $clockSeq): bool
{
    return $clockSeq === null || ($clockSeq >= 0 && $clockSeq <= 63);
}

Try / catch

try {
    $uuid = Uuid::uuid2($domain, $id, null, $clockSeq);
} catch (\Ramsey\Uuid\Exception\DceSecurityException $e) {
    $uuid = Uuid::uuid2($domain, $id); // retry with a generated clock sequence
}

Prevention

When it happens

Trigger: Uuid::uuid2(..., $clockSeq) with values like 1000; reusing a v1 clock sequence constant; passing an unsigned 14-bit value read from another UUID.

Common situations: Porting v1 generation parameters to uuid2(); hardcoded clock sequence from legacy config written for the v1 field width; generated/fuzzed test values outside 0..63.

Related errors


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