{"record":{"id":"c6b3d761abc3dd1d","repo":"ramsey/uuid","slug":"attempting-to-decode-a-non-time-based-uuid-using-o","errorCode":null,"errorMessage":"Attempting to decode a non-time-based UUID using OrderedTimeCodec","messagePattern":"Attempting to decode a non-time-based UUID using OrderedTimeCodec","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"src/Codec/OrderedTimeCodec.php","lineNumber":94,"sourceCode":"     */\n    public function decodeBytes(string $bytes): UuidInterface\n    {\n        if (strlen($bytes) !== 16) {\n            throw new InvalidArgumentException('$bytes string should contain 16 characters.');\n        }\n\n        // Rearrange the bytes to their original order.\n        $rearrangedBytes = $bytes[4] . $bytes[5] . $bytes[6] . $bytes[7]\n            . $bytes[2] . $bytes[3] . $bytes[0] . $bytes[1]\n            . substr($bytes, 8);\n\n        $uuid = parent::decodeBytes($rearrangedBytes);\n\n        /** @phpstan-ignore possiblyImpure.methodCall */\n        $fields = $uuid->getFields();\n\n        if (!$fields instanceof Rfc4122FieldsInterface || $fields->getVersion() !== Uuid::UUID_TYPE_TIME) {\n            throw new UnsupportedOperationException(\n                'Attempting to decode a non-time-based UUID using OrderedTimeCodec',\n            );\n        }\n\n        return $uuid;\n    }\n}\n","sourceCodeStart":76,"sourceCodeEnd":102,"githubUrl":"https://github.com/ramsey/uuid/blob/da5b521600a707d2dd097598464bd3090de850f5/src/Codec/OrderedTimeCodec.php#L76-L102","documentation":"After rearranging bytes back to standard layout and building the UUID, OrderedTimeCodec::decodeBytes() verifies the result is a version 1 (time-based) RFC 4122 UUID and throws UnsupportedOperationException otherwise. So the input was 16 bytes but did not decode to v1: it is either another version (v4 random, v3/v5 name-based) or a standard-layout v1 binary that was never put through OrderedTimeCodec::encodeBinary().","triggerScenarios":"Calling OrderedTimeCodec::decodeBytes() on: the bytes of a v4/v3/v5 UUID; a regular (non-reordered) v1 binary produced by the default codec or StringCodec::encodeBinary(); arbitrary 16 bytes whose version nibble is not 1 after rearranging.","commonSituations":"Encode/decode codec mismatch after adopting ordered-time storage: legacy rows written by StringCodec (or getBytes() on a default factory) decoded by OrderedTimeCodec; mixed old/new rows in one BINARY(16) column; copy of example code that pairs the wrong codec pair.","solutions":["Decode with the same codec family that encoded the bytes: StringCodec::decodeBytes() (or the default factory) for standard-layout v1 binaries.","Migrate legacy rows once: decode with StringCodec, re-encode with OrderedTimeCodec, so a single layout remains in storage.","If input may be mixed, decode with StringCodec and branch on $uuid->getFields()->getVersion() === 1 instead of assuming layout."],"exampleFix":"// before\n$uuid = $orderedTimeCodec->decodeBytes($bytes); // bytes were written by the default codec\n\n// after\n$uuid = $stringCodec->decodeBytes($bytes); // standard layout decodes fine\n// optional one-time migration to ordered layout:\n// $orderedBytes = $orderedTimeCodec->encodeBinary($uuid);","handlingStrategy":"try-catch","validationCode":"// If rows may be standard-layout, decode with StringCodec first and verify version:\n$uuid = $stringCodec->decodeBytes($bytes);\n$fields = $uuid->getFields();\nif (!$fields instanceof \\Ramsey\\Uuid\\Rfc4122\\FieldsInterface || $fields->getVersion() !== Uuid::UUID_TYPE_TIME) {\n    // not a v1 at all - handle before involving OrderedTimeCodec\n}","typeGuard":"function decodesToTimeUuid(string $standardBytes, StringCodec $codec): bool\n{\n    $fields = $codec->decodeBytes($standardBytes)->getFields();\n\n    return $fields instanceof \\Ramsey\\Uuid\\Rfc4122\\FieldsInterface\n        && $fields->getVersion() === \\Ramsey\\Uuid\\Uuid::UUID_TYPE_TIME;\n}","tryCatchPattern":"try {\n    $uuid = $orderedCodec->decodeBytes($bytes);\n} catch (\\Ramsey\\Uuid\\Exception\\UnsupportedOperationException $e) {\n    // Legacy standard-layout row: retry with the standard codec.\n    $uuid = $stringCodec->decodeBytes($bytes);\n    // optionally schedule migration: $orderedCodec->encodeBinary($uuid) if v1\n}","preventionTips":["Encode and decode with the same codec family; document which codec wrote each column.","Run a one-time migration when switching to ordered-time storage so only one layout exists.","Keep a byte-layout marker (or separate table/column) if mixed layouts are unavoidable.","Add a contract test that round-trips encodeBinary()/decodeBytes() for your stored data."],"tags":["php","ramsey-uuid","ordered-time-codec","decode-bytes","uuid-version-mismatch"],"backgroundTag":"uuid-version-mismatch","analyzedSha":"da5b521600a707d2dd097598464bd3090de850f5","analyzedAt":"2026-08-21T01:35:29.252Z","schemaVersion":2},"datasetVersion":"2026-08-21T03:17:12.404Z"}