apache/cassandra · error · InvalidRequestException
PRIMARY KEY column "%s" cannot be restricted as preceding co
Error message
PRIMARY KEY column "%s" cannot be restricted as preceding column "%s" is not restricted
What it means
Clustering columns must be restricted in primary-key order without gaps: you may only restrict clustering column i if all columns before it are also restricted. When a restricted column skips over an unrestricted preceding clustering column, this error names both columns.
Source
Thrown at src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java:705
if (hasClusteringColumnsRestrictions() && clusteringColumnsRestrictions.needFiltering())
{
if (hasQueriableIndex || forView)
{
usesSecondaryIndexing = true;
}
else if (!allowFiltering)
{
List<ColumnMetadata> clusteringColumns = table.clusteringColumns();
List<ColumnMetadata> restrictedColumns = new ArrayList<>(clusteringColumnsRestrictions.columns());
for (int i = 0, m = restrictedColumns.size(); i < m; i++)
{
ColumnMetadata clusteringColumn = clusteringColumns.get(i);
ColumnMetadata restrictedColumn = restrictedColumns.get(i);
if (!clusteringColumn.equals(restrictedColumn))
{
throw invalidRequest("PRIMARY KEY column \"%s\" cannot be restricted as preceding column \"%s\" is not restricted",
restrictedColumn.name,
clusteringColumn.name);
}
}
}
}
}
}
/**
* Returns the clustering columns that are not restricted.
* @return the clustering columns that are not restricted.
*/
private Collection<ColumnIdentifier> getUnrestrictedClusteringColumns()
{
List<ColumnMetadata> missingClusteringColumns = new ArrayList<>(table.clusteringColumns());
missingClusteringColumns.removeAll(new LinkedList<>(clusteringColumnsRestrictions.columns()));View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Add the missing preceding restriction: WHERE pk = ... AND c1 = ... AND c2 = ...
- Use the token/partition design so the high-selectivity column comes first in the PRIMARY KEY definition
- Restrict c1 with an IN list if you don't know its exact value: WHERE pk = ... AND c1 IN (...) AND c2 = ...
- If filtering is genuinely needed, add ALLOW FILTERING (performs a scan within partitions)
Example fix
// before SELECT * FROM events WHERE device_id = 'd1' AND minute = 42; -- hour (first clustering col) skipped // after SELECT * FROM events WHERE device_id = 'd1' AND hour = 1 AND minute = 42;
Defensive patterns
Strategy: validation
Validate before calling
// Verify restricted clustering columns form a prefix of the clustering order:
List<String> clusteringOrder = table.getClusteringColumns().stream().map(ColumnMetadata::getName).collect(Collectors.toList());
List<String> restricted = whereColumns.stream().filter(clusteringOrder::contains).collect(Collectors.toList());
if (!clusteringOrder.subList(0, restricted.size()).equals(restricted.stream().sorted(Comparator.comparingInt(clusteringOrder::indexOf)).collect(Collectors.toList()))) throw new IllegalArgumentException("Clustering columns must be restricted in order without gaps"); Prevention
- Always restrict clustering columns left-to-right in PRIMARY KEY order
- Order the PRIMARY KEY so the most-selective queried column comes first
- Catch gap patterns in a query-construction layer built on table metadata
When it happens
Trigger: SELECT * FROM t WHERE pk = 'a' AND c2 = 'x' while c1 (which precedes c2 in the PRIMARY KEY) is unrestricted; same gap pattern in DELETEs or IN relations.
Common situations: Querying the 'second' clustering key directly — a common modeling mistake; schema changes that reordered clustering columns; multi-column WHERE clauses generated from ORM filters.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Some clustering keys are missing: %s
- Cannot create ENTRIES index on frozen map clustering column
- category %s not found in %s
- GRANT operation is not supported by AllowAllAuthorizer
- REVOKE operation is not supported by AllowAllAuthorizer
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/bdce5c00d0193d59.
Report an issue: GitHub.