{"record":{"id":"262ad6d6da0b2e18","repo":"ramsey/uuid","slug":"fields-used-to-create-a-uuidv8-must-represent-a-ve","errorCode":null,"errorMessage":"Fields used to create a UuidV8 must represent a version 8 (custom format) UUID","messagePattern":"Fields used to create a UuidV8 must represent a version 8 \\(custom format\\) UUID","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/Rfc4122/UuidV8.php","lineNumber":53,"sourceCode":"final class UuidV8 extends Uuid implements UuidInterface\n{\n    /**\n     * Creates a version 8 (custom format) UUID\n     *\n     * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID\n     * @param NumberConverterInterface $numberConverter The number converter to use for converting hex values to/from integers\n     * @param CodecInterface $codec The codec to use when encoding or decoding UUID strings\n     * @param TimeConverterInterface $timeConverter The time converter to use for converting timestamps extracted from a\n     *     UUID to unix timestamps\n     */\n    public function __construct(\n        Rfc4122FieldsInterface $fields,\n        NumberConverterInterface $numberConverter,\n        CodecInterface $codec,\n        TimeConverterInterface $timeConverter,\n    ) {\n        if ($fields->getVersion() !== Uuid::UUID_TYPE_CUSTOM) {\n            throw new InvalidArgumentException(\n                'Fields used to create a UuidV8 must represent a version 8 (custom format) UUID',\n            );\n        }\n\n        parent::__construct($fields, $numberConverter, $codec, $timeConverter);\n    }\n}\n","sourceCodeStart":35,"sourceCodeEnd":61,"githubUrl":"https://github.com/ramsey/uuid/blob/da5b521600a707d2dd097598464bd3090de850f5/src/Rfc4122/UuidV8.php#L35-L61","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before: raw application bytes, version nibble never set\n$uuid = new UuidV8(new Fields($bytes), $numberConverter, $codec, $timeConverter);\n// InvalidArgumentException: Fields used to create a UuidV8 must represent a version 8 (custom format) UUID\n\n// after: let the factory set the version/variant bits\n$uuid = Uuid::uuid8($bytes);\n\n// or set them yourself before building the fields\n$bytes[6] = chr((ord($bytes[6]) & 0x0f) | 0x80);\n$bytes[8] = chr((ord($bytes[8]) & 0x3f) | 0x80);\n$uuid = new UuidV8(new Fields($bytes), $numberConverter, $codec, $timeConverter);","handlingStrategy":"validation","validationCode":"use Ramsey\\Uuid\\Rfc4122\\FieldsInterface;\nuse Ramsey\\Uuid\\Uuid;\n\n// Run before constructing UuidV8\nif ($fields->getVersion() !== Uuid::UUID_TYPE_CUSTOM) {\n    throw new \\InvalidArgumentException(\n        'Cannot build UuidV8 from version ' . $fields->getVersion() . ' fields'\n    );\n}\n\n// Or set the v8 bits before building fields\n$bytes[6] = chr((ord($bytes[6]) & 0x0f) | 0x80);\n$bytes[8] = chr((ord($bytes[8]) & 0x3f) | 0x80);","typeGuard":"use Ramsey\\Uuid\\Rfc4122\\FieldsInterface;\nuse Ramsey\\Uuid\\Rfc4122\\UuidV8;\nuse Ramsey\\Uuid\\Uuid;\n\nfunction isVersion8Fields(FieldsInterface $fields): bool\n{\n    return $fields->getVersion() === Uuid::UUID_TYPE_CUSTOM;\n}\n\n$uuid = Uuid::fromBytes($bytes);\nif ($uuid instanceof UuidV8) {\n    // custom-format UUID\n}","tryCatchPattern":"use Ramsey\\Uuid\\Exception\\InvalidArgumentException;\n\ntry {\n    $uuid = new UuidV8($fields, $numberConverter, $codec, $timeConverter);\n} catch (InvalidArgumentException $e) {\n    $uuid = Uuid::uuid8($originalBytes); // let the factory set the bits correctly\n}","preventionTips":["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"],"tags":["php","ramsey-uuid","uuid","validation","constructor","version-mismatch","uuidv8","custom-format"],"backgroundTag":"uuid-version-mismatch","analyzedSha":"da5b521600a707d2dd097598464bd3090de850f5","analyzedAt":"2026-08-21T01:35:29.252Z","schemaVersion":2},"datasetVersion":"2026-08-21T03:17:12.404Z"}