ramsey/uuid · error · InvalidArgumentException
Fields used to create a UuidV2 must represent a version 2 (D
Error message
Fields used to create a UuidV2 must represent a version 2 (DCE Security) UUID
What it means
Ramsey\Uuid\Rfc4122\UuidV2 wraps an existing field set that must represent a version 2 (DCE Security) UUID. Its constructor verifies the version nibble via $fields->getVersion() against Uuid::UUID_TYPE_DCE_SECURITY (2) and throws Ramsey\Uuid\Exception\InvalidArgumentException on any other value. The guard exists because UuidV2 exposes version-specific accessors (getLocalDomain(), getLocalIdentifier(), getLocalNode()) that would return meaningless data for mismatched fields. In normal usage you never call this constructor directly; the factory and builder call it only for bytes whose version nibble is 2.
Source
Thrown at src/Rfc4122/UuidV2.php:70
use TimeTrait;
/**
* Creates a version 2 (DCE Security) UUID
*
* @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
* @param NumberConverterInterface $numberConverter The number converter to use for converting hex values to/from integers
* @param CodecInterface $codec The codec to use when encoding or decoding UUID strings
* @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a
* UUID to unix timestamps
*/
public function __construct(
Rfc4122FieldsInterface $fields,
NumberConverterInterface $numberConverter,
CodecInterface $codec,
TimeConverterInterface $timeConverter,
) {
if ($fields->getVersion() !== Uuid::UUID_TYPE_DCE_SECURITY) {
throw new InvalidArgumentException(
'Fields used to create a UuidV2 must represent a version 2 (DCE Security) UUID'
);
}
parent::__construct($fields, $numberConverter, $codec, $timeConverter);
}
/**
* Returns the local domain used to create this version 2 UUID
*/
public function getLocalDomain(): int
{
/** @var Rfc4122FieldsInterface $fields */
$fields = $this->getFields();
return (int) hexdec($fields->getClockSeqLow()->toString());
}
View on GitHub (pinned to da5b521600)
Solutions
- Generate version 2 UUIDs through the factory: Uuid::uuid2($localDomain, $identifier, $node, $clockSeq) instead of new UuidV2(...)
- When wrapping existing values, use Uuid::fromString($string) or Uuid::fromBytes($bytes) — the builder selects the version-matching class automatically
- If you must construct manually, first verify $fields->getVersion() === Uuid::UUID_TYPE_DCE_SECURITY and fix the version bits in the input bytes when it differs
- In a custom builder, switch on $fields->getVersion() and instantiate UuidV2 only for version 2; fall back to the base Ramsey\Uuid\Uuid class for other versions
Example fix
// before: fields carry version 4 bits, but UuidV2 is constructed directly $uuid = new UuidV2($fields, $numberConverter, $codec, $timeConverter); // InvalidArgumentException: Fields used to create a UuidV2 must represent a version 2 (DCE Security) UUID // after: generate v2 UUIDs through the factory $uuid = Uuid::uuid2(Uuid::DCE_DOMAIN_PERSON, 1001); // or wrap existing bytes with the version-agnostic builder $uuid = Uuid::fromBytes($bytes); // returns UuidV2 only when the version nibble is 2
Defensive patterns
Strategy: validation
Validate before calling
use Ramsey\Uuid\Rfc4122\FieldsInterface;
use Ramsey\Uuid\Uuid;
// Run before constructing UuidV2
if ($fields->getVersion() !== Uuid::UUID_TYPE_DCE_SECURITY) {
// do not construct UuidV2 with these fields
throw new \InvalidArgumentException(
'Cannot build UuidV2 from version ' . $fields->getVersion() . ' fields'
);
} Type guard
use Ramsey\Uuid\Rfc4122\FieldsInterface;
use Ramsey\Uuid\Rfc4122\UuidV2;
use Ramsey\Uuid\Uuid;
function isVersion2Fields(FieldsInterface $fields): bool
{
return $fields->getVersion() === Uuid::UUID_TYPE_DCE_SECURITY;
}
// after decoding, narrow instead of assuming
$uuid = Uuid::fromString($value);
if ($uuid instanceof UuidV2) {
$domain = $uuid->getLocalDomain();
} Try / catch
use Ramsey\Uuid\Exception\InvalidArgumentException;
try {
$uuid = new UuidV2($fields, $numberConverter, $codec, $timeConverter);
} catch (InvalidArgumentException $e) {
// Log the actual version and fall back to the version-agnostic class
$uuid = new Ramsey\Uuid\Uuid($fields, $numberConverter, $codec, $timeConverter);
} Prevention
- Prefer Uuid::uuid2() for generation and Uuid::fromString()/fromBytes() for wrapping — they never throw this error
- Check $fields->getVersion() before instantiating any version-specific UuidV* class
- Never assume a decoded UUID's version; switch on getVersion()
- In custom builders, map each version to its class and default to the base Uuid
When it happens
Trigger: Calling new UuidV2($fields, $numberConverter, $codec, $timeConverter) with a Ramsey\Uuid\Rfc4122\Fields instance whose version nibble is not 2 — for example fields decoded from a v4 string via a codec, or bytes produced by Uuid::uuid4()/uuid1(). Also a custom Builder or Codec that unconditionally instantiates UuidV2 for every UUID it decodes.
Common situations: Copying low-level constructor examples instead of using the factory; custom codecs/builders (e.g. GUID byte-order handling on little-endian systems) that map every decoded UUID to one version class; test fixtures that hand-assemble field sets with the wrong version bits; mutating UUID bytes without fixing the version nibble.
Related errors
- Fields used to create a UuidV3 must represent a version 3 (n
- Fields used to create a UuidV4 must represent a version 4 (r
- Fields used to create a UuidV5 must represent a version 5 (n
- Fields used to create a UuidV7 must represent a version 7 (U
- Fields used to create a UuidV8 must represent a version 8 (c
AI-assisted analysis of ramsey/uuid@da5b521600 (2026-08-21).
Data as JSON: /api/errors/36b4b5d784c332cf.
Report an issue: GitHub.