apache/cassandra · error · InvalidRequestException

duration type is not supported for PRIMARY KEY column

Error message

duration type is not supported for PRIMARY KEY column '%s'

What it means

Thrown from CreateTableStatement's builder while validating PRIMARY KEY columns when a key column's type is a Duration. Durations cannot be serialized in a deterministic byte-comparable way for partitioning/clustering, so using them in a PRIMARY KEY is rejected.

Solutions

  1. Use timestamp, time, or bigint (e.g. nanoseconds) as the key column instead of duration
  2. Keep the duration column as a regular non-key column
  3. Convert durations to a fixed-unit numeric representation before keying

Example fix

// before
CREATE TABLE t (d duration, v int, PRIMARY KEY (d));
// after
CREATE TABLE t (d bigint, v int, PRIMARY KEY (d)); // duration stored as nanoseconds
Defensive patterns

Strategy: validation

Validate before calling

if (keyColumnType.referencesDuration()) throw new IllegalArgumentException("duration cannot be used in PRIMARY KEY; use bigint/timestamp instead");

Try / catch

try { session.execute(ddl); } catch (InvalidRequestException e) { if (e.getMessage().contains("duration type is not supported for PRIMARY KEY")) { /* substitute a numeric/timestamp key type */ } else throw e; }

Prevention

When it happens

Trigger: Declaring a partition or clustering column as `duration` or a type that references duration (e.g. a frozen collection/UDT containing duration) and using it in the PRIMARY KEY.

Common situations: Storing time intervals as key components; users assuming duration behaves like timestamp/uuid in keys.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/cql3/statements/schema/CreateTableStatement.java:315

            if (!primaryKeyColumns.add(column))
                throw ire("Duplicate column '%s' in PRIMARY KEY clause for table '%s'", column, tableName);

            AbstractType<?> type = properties.type;
            if (type.isMultiCell())
            {
                CQL3Type cqlType = properties.cqlType;
                if (type.isCollection())
                    throw ire("Invalid non-frozen collection type %s for PRIMARY KEY column '%s'", cqlType, column);
                else
                    throw ire("Invalid non-frozen user-defined type %s for PRIMARY KEY column '%s'", cqlType, column);
            }

            if (type.isCounter())
                throw ire("counter type is not supported for PRIMARY KEY column '%s'", column);

            if (type.referencesDuration())
                throw ire("duration type is not supported for PRIMARY KEY column '%s'", column);

            if (staticColumns.contains(column))
                throw ire("Static column '%s' cannot be part of the PRIMARY KEY", column);
        });

        List<ColumnProperties> partitionKeyColumnProperties = new ArrayList<>();
        List<ColumnProperties> clusteringColumnProperties = new ArrayList<>();

        partitionKeyColumns.forEach(column ->
        {
            ColumnProperties columnProperties = columns.remove(column);
            partitionKeyColumnProperties.add(columnProperties);
        });

        clusteringColumns.forEach(column ->
        {
            ColumnProperties columnProperties = columns.remove(column);
            boolean reverse = !clusteringOrder.getOrDefault(column, true);

View on GitHub (pinned to 88fd0f6a0e)