ramsey/uuid · error · InvalidArgumentException
Fields used to create a UuidV8 must represent a version 8 (c
Error message
Fields used to create a UuidV8 must represent a version 8 (custom format) UUID
What it means
Ramsey\Uuid\Rfc4122\UuidV8 wraps a field set that must represent a version 8 (custom format) UUID. The constructor checks $fields->getVersion() against Uuid::UUID_TYPE_CUSTOM (8) and throws Ramsey\Uuid\Exception\InvalidArgumentException otherwise. Version 8 is the RFC 9562 escape hatch for application-defined layouts, so the guard only asserts that the custom nibble was set deliberately. In practice you create v8 values with Uuid::uuid8($bytes), which overwrites the version and variant bits for you.
Source
Thrown at src/Rfc4122/UuidV8.php:53
final class UuidV8 extends Uuid implements UuidInterface
{
/**
* Creates a version 8 (custom format) 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_CUSTOM) {
throw new InvalidArgumentException(
'Fields used to create a UuidV8 must represent a version 8 (custom format) UUID',
);
}
parent::__construct($fields, $numberConverter, $codec, $timeConverter);
}
}
View on GitHub (pinned to da5b521600)
Solutions
- Create v8 UUIDs with Uuid::uuid8($bytes) — it sets the version and variant bits itself
- Before constructing UuidV8 manually, set the version nibble: $bytes[6] = chr((ord($bytes[6]) & 0x0f) | 0x80) and the variant: $bytes[8] = chr((ord($bytes[8]) & 0x3f) | 0x80)
- Check $fields->getVersion() === Uuid::UUID_TYPE_CUSTOM first and fail with a clear domain error if not
- Use the base Ramsey\Uuid\Uuid class when you do not need version-specific behavior
Example fix
// before: raw application bytes, version nibble never set $uuid = new UuidV8(new Fields($bytes), $numberConverter, $codec, $timeConverter); // InvalidArgumentException: Fields used to create a UuidV8 must represent a version 8 (custom format) UUID // after: let the factory set the version/variant bits $uuid = Uuid::uuid8($bytes); // or set them yourself before building the fields $bytes[6] = chr((ord($bytes[6]) & 0x0f) | 0x80); $bytes[8] = chr((ord($bytes[8]) & 0x3f) | 0x80); $uuid = new UuidV8(new Fields($bytes), $numberConverter, $codec, $timeConverter);
Defensive patterns
Strategy: validation
Validate before calling
use Ramsey\Uuid\Rfc4122\FieldsInterface;
use Ramsey\Uuid\Uuid;
// Run before constructing UuidV8
if ($fields->getVersion() !== Uuid::UUID_TYPE_CUSTOM) {
throw new \InvalidArgumentException(
'Cannot build UuidV8 from version ' . $fields->getVersion() . ' fields'
);
}
// Or set the v8 bits before building fields
$bytes[6] = chr((ord($bytes[6]) & 0x0f) | 0x80);
$bytes[8] = chr((ord($bytes[8]) & 0x3f) | 0x80); Type guard
use Ramsey\Uuid\Rfc4122\FieldsInterface;
use Ramsey\Uuid\Rfc4122\UuidV8;
use Ramsey\Uuid\Uuid;
function isVersion8Fields(FieldsInterface $fields): bool
{
return $fields->getVersion() === Uuid::UUID_TYPE_CUSTOM;
}
$uuid = Uuid::fromBytes($bytes);
if ($uuid instanceof UuidV8) {
// custom-format UUID
} Try / catch
use Ramsey\Uuid\Exception\InvalidArgumentException;
try {
$uuid = new UuidV8($fields, $numberConverter, $codec, $timeConverter);
} catch (InvalidArgumentException $e) {
$uuid = Uuid::uuid8($originalBytes); // let the factory set the bits correctly
} Prevention
- Use Uuid::uuid8($bytes) — it sets the version and variant bits itself
- When packing custom bytes manually, always set bits 48-51 to 0b1000 and the variant bits
- Assert the version nibble before direct construction
- Keep custom-layout constants in one place so the bit-twiddling cannot drift
When it happens
Trigger: Calling new UuidV8($fields, $numberConverter, $codec, $timeConverter) with fields whose version nibble is not 8 — e.g. raw application bytes packed without setting the version nibble, or fields decoded from a v4 UUID. Also constructing UuidV8 from bytes passed through substr/pack incorrectly.
Common situations: Building custom-layout UUIDs by hand (pack() of 16 bytes) and forgetting to set bits 48-51 to 0b1000; porting bespoke binary identifiers to ramsey/uuid; custom builders hardcoding UuidV8 for all internal identifiers.
Related errors
- Fields used to create a UuidV2 must represent a version 2 (D
- 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
AI-assisted analysis of ramsey/uuid@da5b521600 (2026-08-21).
Data as JSON: /api/errors/262ad6d6da0b2e18.
Report an issue: GitHub.