ramsey/uuid · error · DceSecurityException
Local domain must be a valid DCE Security domain
Error message
Local domain must be a valid DCE Security domain
What it means
DceSecurityGenerator::generate() (the engine behind Uuid::uuid2(), version 2 UUIDs) requires the local domain to be one of the three DCE Security domains: Uuid::DCE_DOMAIN_PERSON (0), Uuid::DCE_DOMAIN_GROUP (1), Uuid::DCE_DOMAIN_ORG (2). Anything else throws DceSecurityException.
Source
Thrown at src/Generator/DceSecurityGenerator.php:69
* Lower bounds for the clock sequence in DCE Security UUIDs.
*/
private const CLOCK_SEQ_LOW = 0;
public function __construct(
private NumberConverterInterface $numberConverter,
private TimeGeneratorInterface $timeGenerator,
private DceSecurityProviderInterface $dceSecurityProvider,
) {
}
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');
}
View on GitHub (pinned to da5b521600)
Solutions
- Always pass the constants: Uuid::DCE_DOMAIN_PERSON, Uuid::DCE_DOMAIN_GROUP, or Uuid::DCE_DOMAIN_ORG.
- Map domain names to constants before calling: ['person'=>0,'group'=>1,'org'=>2][$name] ?? fail.
- Re-check the uuid2() argument order if the value you meant for another slot lands in $localDomain.
Example fix
// before
$uuid = Uuid::uuid2('org'); // string -> DceSecurityException
// after
$uuid = Uuid::uuid2(Uuid::DCE_DOMAIN_ORG, new Integer(42)); Defensive patterns
Strategy: validation
Validate before calling
const DCE_DOMAINS = [
Uuid::DCE_DOMAIN_PERSON,
Uuid::DCE_DOMAIN_GROUP,
Uuid::DCE_DOMAIN_ORG,
];
if (!in_array($localDomain, DCE_DOMAINS, true)) {
throw new InvalidArgumentException('local domain must be person (0), group (1) or org (2)');
}
$uuid = Uuid::uuid2($localDomain, $identifier); Type guard
function isDceDomain(int $domain): bool
{
return in_array($domain, [Uuid::DCE_DOMAIN_PERSON, Uuid::DCE_DOMAIN_GROUP, Uuid::DCE_DOMAIN_ORG], true);
} Try / catch
try {
$uuid = Uuid::uuid2($domain, $id);
} catch (\Ramsey\Uuid\Exception\DceSecurityException $e) {
throw new InvalidConfigurationException('bad DCE domain configuration', $e);
} Prevention
- Always use the Uuid::DCE_DOMAIN_* constants, never raw ints from config.
- Map domain strings to constants at the config-loading boundary.
- Review uuid2()'s positional signature when adding arguments.
- Validate the domain in one place (factory wrapper) instead of every call site.
When it happens
Trigger: Uuid::uuid2(3); Uuid::uuid2('person') (string, not the int constant); passing a clock sequence or identifier in the domain position; casting a domain name from config straight to an int.
Common situations: Positional-argument mix-ups in uuid2($localDomain, $localIdentifier, $node, $clockSeq); storing domains as strings and letting PHP coerce them; inventing custom domains instead of using the constants.
Related errors
- Local identifier out of bounds; it must be a value between 0
- Clock sequence out of bounds; it must be a value between 0 a
- A local identifier must be provided for the org domain
- Unable to get a user identifier using the system DCE Securit
- Unable to get a group identifier using the system DCE Securi
AI-assisted analysis of ramsey/uuid@da5b521600 (2026-08-21).
Data as JSON: /api/errors/58d678fc701dc51c.
Report an issue: GitHub.