apache/cassandra · error · MarshalException

Invalid UUID version

Error message

Invalid UUID version %d for timeuuid

What it means

verifyVersion checks the UUID version nibble of the high bits and throws when it is not 1. timeuuid values in Cassandra are RFC 4122 version-1 (time-based) UUIDs; any other version stored in a timeuuid column is rejected during comparison or comparable-bytes conversion.

Solutions

  1. Generate proper version-1 time UUIDs (e.g. UUIDGen.getTimeUUID(), or TimeUUID.Generator) instead of random UUIDs.
  2. Parse/validate client-side: check uuid.version() == 1 before sending to a timeuuid column.
  3. Change the column type to uuid if version-4 UUIDs are intended.

Example fix

// before
UUID id = UUID.randomUUID(); // version 4
// after
UUID id = UUIDGen.getTimeUUID(); // version 1 timeuuid
Defensive patterns

Strategy: validation

Validate before calling

UUID u = /* candidate */;
if (u == null || u.version() != 1) throw new IllegalArgumentException("timeuuid must be version 1");

Type guard

boolean isTimeUUID(java.util.UUID u) { return u != null && u.version() == 1; }

Try / catch

catch (MarshalException e) { log.warn("non-v1 uuid in timeuuid column: {}", e.getMessage()); regenerateTimeUUID(); }

Prevention

When it happens

Trigger: Comparing values of AbstractTimeUUIDType (compareCustom, asComparableBytes) or calling fromComparableBytes with a 16-byte value whose UUID version nibble is not 1 (e.g. version 4 random UUID bytes) stored in a timeuuid column.

Common situations: Inserting a random UUID (java.util.UUID.randomUUID()) into a timeuuid column via raw bytes or drivers that don't validate; application code generating non-v1 UUIDs; corrupted binary data.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/007e59050b9c5891. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/db/marshal/AbstractTimeUUIDType.java:135

        // In addition, TimeUUIDType also touches the low bits of the UUID (see CASSANDRA-8730 and DB-1758).
        loBits ^= 0x8080808080808080L;

        return UUIDType.makeUuidBytes(accessor, hiBits, loBits);
    }

    // takes as input 8 signed bytes in native machine order
    // returns the first byte unchanged, and the following 7 bytes converted to an unsigned representation
    // which is the same as a 2's complement long in native format
    public static long signedBytesToNativeLong(long signedBytes)
    {
        return signedBytes ^ 0x0080808080808080L;
    }

    private void verifyVersion(long hiBits)
    {
        long version = (hiBits >>> 12) & 0xF;
        if (version != 1)
            throw new MarshalException(String.format("Invalid UUID version %d for timeuuid",
                                                     version));
    }

    protected static long reorderTimestampBytes(long input)
    {
        return (input <<  48)
               | ((input <<  16) & 0xFFFF00000000L)
               |  (input >>> 32);
    }

    protected static long reorderBackTimestampBytes(long input)
    {
        // In a time-based UUID the high bits are significantly more shuffled than in other UUIDs - if [X] represents a
        // 16-bit tuple, [1][2][3][4] should become [3][4][2][1].
        // See the UUID Javadoc (and more specifically the high bits layout of a Leach-Salz UUID) to understand the
        // reasoning behind this bit twiddling in the first place (in the context of comparisons).
        return (input << 32)
               | ((input >>> 16) & 0xFFFF0000L)

View on GitHub (pinned to 88fd0f6a0e)