apache/cassandra · error · InvalidRequestException
Secondary indexes are not supported on PRIMARY KEY columns…
Error message
Secondary indexes are not supported on PRIMARY KEY columns in COMPACT STORAGE tables
What it means
In COMPACT STORAGE (thrift-legacy) tables, primary key columns have a restricted on-disk encoding and cannot be indexed by a legacy secondary index. Creating a 2i on any PRIMARY KEY column of a compact table throws InvalidRequestException (PRIMARY_KEY_IN_COMPACT_STORAGE).
Solutions
- Run `ALTER TABLE ... DROP COMPACT STORAGE` (after cluster upgrade prerequisites) to convert the table, then create the index.
- Query the primary-key column directly by its key instead of indexing it.
- Migrate data to a new non-compact table with the desired index and switch reads over.
Example fix
-- before CREATE INDEX ON legacy_compact (clustering_col); -- fails -- after ALTER TABLE legacy_compact DROP COMPACT STORAGE; CREATE INDEX ON legacy_compact (clustering_col);
Defensive patterns
Strategy: validation
Validate before calling
TableMetadata t = session.getCluster().getMetadata().getKeyspace("ks").getTable("t");
boolean compact = t.getOptions().getCompactStorage();
boolean isPkCol = t.getPartitionKey().stream().anyMatch(c -> c.getName().equals(col))
|| t.getClusteringColumns().keySet().stream().anyMatch(c -> c.getName().equals(col));
if (compact && isPkCol) throw new IllegalStateException("cannot 2i a PK column of a COMPACT STORAGE table"); Try / catch
try { session.execute("CREATE INDEX ON ks.t (pkcol)"); }
catch (InvalidQueryException e) {
if (e.getMessage().contains("PRIMARY KEY columns in COMPACT STORAGE"))
throw new IllegalStateException("DROP COMPACT STORAGE first or query by key", e);
throw e;
} Prevention
- Plan to DROP COMPACT STORAGE on legacy tables before adding indexes
- Remember primary key columns are already queryable by key — indexing them is usually unnecessary
- Audit thrift-era tables for COMPACT STORAGE before writing migration DDL
When it happens
Trigger: `CREATE INDEX ... ON compact_table (primary_key_column)` where the table was created `WITH COMPACT STORAGE` and the target column `isPrimaryKeyColumn()` is true (partition key or clustering column).
Common situations: Working with thrift-era CQL3 tables kept COMPACT STORAGE for compatibility; migration scripts that blindly index all columns.
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
- Secondary indexes are not supported on compact value column…
- Cannot add new column to a COMPACT STORAGE table
- Cannot create ENTRIES index on frozen map clustering column
- Cannot create index on
- Cannot create () index on frozen column . Frozen…
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/e036517f048f7975.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java:283
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);
if (target.type == Type.FULL && isNonSAIIndex && (!baseType.isCollection() || column.type.isMultiCell()))
throw ire(FULL_ON_FROZEN_COLLECTIONS);
if (!baseType.isCollection() && target.type != Type.SIMPLE)
throw ire(NON_COLLECTION_SIMPLE_INDEX, target.type, column);
// Frozen collections are only supported with SAI indexes.
if (isNonSAIIndex && baseType.isCollection() && !column.type.isMultiCell())
{
if (target.type == Type.VALUES || target.type == Type.KEYS || target.type == Type.KEYS_AND_VALUES)
{View on GitHub (pinned to 88fd0f6a0e)