apache/cassandra · error · InvalidRequestException
ANN ordering by vector requires all restricted column(s) to…
Error message
ANN ordering by vector requires all restricted column(s) to be indexed
What it means
Thrown when an ANN query combines the ANN ordering with additional filtering (non-ANN restrictions on other columns) where at least one filtered column lacks a supporting index. Cassandra requires every non-ANN restriction in an ANN query to be served by an index so the filtering happens in the indexed/ANN path, not as a post-filter scan.
Solutions
- Create indexes on every non-ANN column used in the WHERE clause of the ANN query.
- Remove the unindexed filter predicates and post-filter results client-side after the ANN search.
- Ensure partition key restrictions are direct equality (not filtering) and clustering filters are indexed.
- Denormalize the data so metadata filters become partition-key equalities in a query table.
Example fix
// before SELECT * FROM t WHERE cat = 'a' ORDER BY v ANN OF [0.1,0.2]; -- cat not indexed // after CREATE INDEX ON t (cat); SELECT * FROM t WHERE cat = 'a' ORDER BY v ANN OF [0.1,0.2];
Defensive patterns
Strategy: validation
Validate before calling
// every non-ANN WHERE column in an ANN query must be indexed
List<String> nonAnn = whereColumns.stream().filter(c -> !c.equals(annColumn)).collect(toList());
for (String c : nonAnn)
if (!isIndexed(table, c)) throw new IllegalStateException("ANN query filter column not indexed: " + c); Try / catch
try { session.execute(query); } catch (InvalidRequestException e) { if (e.getMessage().contains("all restricted column(s) to be indexed")) postFilterClientSide(); else throw e; } Prevention
- Index all metadata columns used alongside ANN filters at schema creation.
- Prefer partition-key equality over filter columns for hybrid vector search.
- Review any new filter added to ANN queries for index coverage.
When it happens
Trigger: `SELECT * FROM t WHERE cat = 'a' ORDER BY v ANN OF [...]` where v is indexed but cat is not; ANN query with clustering/partition filtering columns that are not indexed; combining ANN with several predicates, some unindexed.
Common situations: Hybrid vector+metadata search where metadata columns were never indexed; indexes exist for some but not all filter columns; adding new filter columns to an existing ANN query without indexing them.
Related errors
- ANN ordering by vector requires the column to be indexed
- ANN ordering does not support any other ordering
- ANN ordering is only supported on float vector indexes
- Cannot execute this query as it might involve data…
- Cannot specify more than one ANN ordering
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/3f14ab1fb7ffad5c.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java:337
throw invalidRequest("Non PRIMARY KEY columns found in where clause: %s ",
Joiner.on(", ").join(nonPrimaryKeyColumns));
}
Optional<SingleRestriction> annRestriction = Streams.stream(nonPrimaryKeyRestrictions)
.filter(SingleRestriction::isANN)
.findFirst();
if (annRestriction.isPresent())
{
// If there is an ANN restriction then it must be for a vector<float, n> column, and it must have an index
ColumnMetadata annColumn = annRestriction.get().firstColumn();
if (!annColumn.type.isVector() || !(((VectorType<?>)annColumn.type).elementType instanceof FloatType))
throw invalidRequest(ANN_ONLY_SUPPORTED_ON_VECTOR_MESSAGE);
if (indexRegistry == null || indexRegistry.listIndexes().stream().noneMatch(i -> i.dependsOn(annColumn)))
throw invalidRequest(ANN_REQUIRES_INDEX_MESSAGE);
// We do not allow ANN queries using partition key restrictions that need filtering
if (partitionKeyRestrictions.needFiltering())
throw invalidRequest(ANN_REQUIRES_INDEXED_FILTERING_MESSAGE);
// We do not allow ANN query filtering using non-indexed columns
List<ColumnMetadata> nonAnnColumns = Streams.stream(nonPrimaryKeyRestrictions)
.filter(r -> !r.isANN())
.map(SingleRestriction::firstColumn)
.collect(Collectors.toList());
List<ColumnMetadata> clusteringColumns = clusteringColumnsRestrictions.columns();
if (!nonAnnColumns.isEmpty() || !clusteringColumns.isEmpty())
{
List<ColumnMetadata> nonIndexedColumns = Stream.concat(nonAnnColumns.stream(), clusteringColumns.stream())
.filter(c -> indexRegistry.listIndexes().stream().noneMatch(i -> i.dependsOn(c)))
.collect(Collectors.toList());
if (!nonIndexedColumns.isEmpty())
{
// restrictions on non-clustering columns, or clusterings that still need filtering, are invalid
if (!clusteringColumns.containsAll(nonIndexedColumns)
|| partitionKeyRestrictions.hasUnrestrictedPartitionKeyComponents()
|| clusteringColumnsRestrictions.needFiltering())
throw invalidRequest(StatementRestrictions.ANN_REQUIRES_INDEXED_FILTERING_MESSAGE);View on GitHub (pinned to 88fd0f6a0e)