apache/cassandra · error · InvalidRequestException
Secondary indexes are not supported on tuples containing dur
Error message
Secondary indexes are not supported on tuples containing durations
What it means
Cassandra rejects secondary indexes on tuple columns that contain a `duration` component. Duration cannot participate in index equality/range semantics, so any tuple referencing duration is unindexable. Raised in validateIndexTarget when the column type is a tuple referencing duration.
Source
Thrown at src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java:271
if (null == column)
throw ire(COLUMN_DOES_NOT_EXIST, target.column);
AbstractType<?> baseType = column.type.unwrap();
boolean isNonSAIIndex = !isSAIIndex(attrs);
// TODO: this check needs to be removed with CASSANDRA-20235
if ((kind == IndexMetadata.Kind.CUSTOM))
validateCustomIndexColumnName(target.column.toString());
if (column.type.referencesDuration())
{
if (column.type.isCollection())
throw ire(COLLECTIONS_WITH_DURATIONS_NOT_SUPPORTED);
if (column.type.isTuple())
throw ire(TUPLES_WITH_DURATIONS_NOT_SUPPORTED);
if (column.type.isUDT())
throw ire(UDTS_WITH_DURATIONS_NOT_SUPPORTED);
throw ire(DURATIONS_NOT_SUPPORTED);
}
if (table.isCompactTable())
{
TableMetadata.CompactTableMetadata compactTable = (TableMetadata.CompactTableMetadata) table;
if (column.isPrimaryKeyColumn())
throw new InvalidRequestException(PRIMARY_KEY_IN_COMPACT_STORAGE);
if (compactTable.compactValueColumn.equals(column))
throw new InvalidRequestException(COMPACT_COLUMN_IN_COMPACT_STORAGE);
}
if (column.isPartitionKey() && table.partitionKeyColumns().size() == 1)
throw ire(ONLY_PARTITION_KEY, column);View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Replace the duration component with an indexable numeric type (bigint milliseconds) or timestamp.
- Split the tuple into separate columns and index only the non-duration ones.
- Use a materialized view / denormalized table keyed by the values you need to query.
Example fix
// before CREATE INDEX ON measurements (window); // window frozen<tuple<timestamp, duration>> // after ALTER TABLE measurements ADD window_ms frozen<tuple<timestamp, bigint>>; CREATE INDEX ON measurements (window_ms);
Defensive patterns
Strategy: validation
Validate before calling
if (column.type.isTuple() && column.type.referencesDuration()) throw new Error('unindexable tuple: contains duration'); Type guard
const isIndexableTuple = (t) => t.isTuple() && !t.referencesDuration();
Try / catch
try { session.execute(ddl); } catch (e) { if (/not supported on tuples containing durations/.test(e.message)) { /* replace duration component */ } else throw e; } Prevention
- Prefer separate numeric columns over tuples containing duration
- Check tuple component types before generating index DDL
When it happens
Trigger: `CREATE INDEX ON t (tuple_col)` where tuple_col is e.g. frozen<tuple<int, duration>> or tuple<duration, text>, via CREATE INDEX / CREATE CUSTOM INDEX.
Common situations: Modeling (offset, duration) pairs in a tuple for range queries then adding an index; upgrading a schema that swapped a timestamp component for duration.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Secondary indexes are not supported on collections containin
- Secondary indexes are not supported on UDTs containing durat
- Secondary indexes are not supported on duration columns
- Not enough bytes to read size of %dth component
- Not enough bytes to read %dth component
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/52d8d7d15b475b33.
Report an issue: GitHub.