apache/cassandra · error · InvalidRequestException

Clustering column restrictions require the use of secondary…

Error message

Clustering column restrictions require the use of secondary indices or filtering for map-element restrictions and for the following operators: %s

What it means

Certain clustering column restrictions (map-element access like c['k'] = v, and operators such as CONTAINS, !=, LIKE, NEQ, NOT IN) cannot be satisfied by normal key matching; they require a secondary index or ALLOW FILTERING. When none is present, StatementRestrictions throws this error listing the offending operators.

Solutions

  1. Append ALLOW FILTERING if the restricted partition is small and performance is acceptable
  2. Create a secondary/custom index on the clustering column (e.g. index on keys(entry_map) or values(entry_map))
  3. Rewrite the query to use only EQ/IN/slice operators on clustering columns
  4. Restructure the schema (e.g. promote the map key into the clustering key) for direct lookup

Example fix

// before
SELECT * FROM t WHERE pk = 'a' AND attrs['env'] = 'prod';
// after
CREATE INDEX t_attrs_keys ON t (KEYS(attrs));
SELECT * FROM t WHERE pk = 'a' AND attrs['env'] = 'prod';
Defensive patterns

Strategy: validation

Validate before calling

// Only allow EQ/IN/slice operators on clustering columns without an index;
// flag map-element access (c['k']) and CONTAINS/!=/NOT IN as requiring index or ALLOW FILTERING.

Prevention

When it happens

Trigger: SELECT * FROM t WHERE pk = 'a' AND clustering_map['key'] = 'v' with no index and no ALLOW FILTERING; clustering column with CONTAINS / != / NOT IN relations without an index.

Common situations: Filtering on map entries inside clustering columns; using inequality or negation operators on clustering keys inherited from SQL habits; queries that worked because an index was later dropped.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java:680

    private void processClusteringColumnsRestrictions(boolean hasQueriableIndex,
                                                      boolean selectsOnlyStaticColumns,
                                                      boolean forView,
                                                      boolean allowFiltering)
    {
        checkFalse(!type.allowClusteringColumnSlices() && clusteringColumnsRestrictions.hasSlice(),
                   "Slice restrictions are not supported on the clustering columns in %s statements", type);

        if (!type.allowClusteringColumnSlices()
            && (!table.isCompactTable() || (table.isCompactTable() && !hasClusteringColumnsRestrictions())))
        {
            if (!selectsOnlyStaticColumns && hasUnrestrictedClusteringColumns())
                throw invalidRequest("Some clustering keys are missing: %s",
                                     Joiner.on(", ").join(getUnrestrictedClusteringColumns()));
        }
        else
        {
            if (clusteringColumnsRestrictions.needsFilteringOrIndexing() && !hasQueriableIndex && !allowFiltering)
                throw invalidRequest("Clustering column restrictions require the use of secondary indices" +
                                     " or filtering for map-element restrictions and for the following operators: %s",
                                     Operator.operatorsRequiringFilteringOrIndexingFor(ColumnMetadata.Kind.CLUSTERING)
                                             .stream()
                                             .map(Operator::toString)
                                             .collect(Collectors.joining(", ")));

            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++)

View on GitHub (pinned to 88fd0f6a0e)