apache/cassandra · error · QueryReferencingTooManyIndexesException

Query attempted to read from too many indexes ( ) but max…

Error message

Query %s attempted to read from too many indexes (%s) but max allowed is %s; query aborted (see sai_sstable_indexes_per_query_fail_threshold)

What it means

QueryController.guardrails aborts a query that would need to reference more SAI SSTable indexes than the sai_sstable_indexes_per_query_fail_threshold guardrail allows. It throws QueryReferencingTooManyIndexesException with the CQL string, index count, and configured threshold. A lower warning threshold logs a warning instead.

Solutions

  1. Reduce the number of indexed columns in the query's WHERE clause
  2. Raise sai_sstable_indexes_per_query_fail_threshold via guardrails if resources allow
  3. Compact SSTables to reduce the number of referenced SSTable indexes
  4. Split the query into fewer indexed predicates

Example fix

// before
SELECT * FROM t WHERE a = 1 AND b = 2 AND c = 3 AND d = 4; // exceeds threshold
// after
ALTER TABLE guardrails SETTINGS ...; -- or via cassandra.yaml:
-- raise sai_sstable_indexes_per_query_fail_threshold, or query fewer columns:
SELECT * FROM t WHERE a = 1 AND b = 2;
Defensive patterns

Strategy: validation

Validate before calling

int referenced = countSaiIndexesInWhereClause(cql); // client-side count
if (referenced > maxThreshold) splitQuery();

Try / catch

try {
    session.execute(cql);
} catch (QueryReferencingTooManyIndexesException e) {
    // reduce indexed predicates or raise the guardrail threshold
}

Prevention

When it happens

Trigger: Running a SELECT whose WHERE clause spans indexes that collectively reference more distinct SSI (SSTable-attached indexes) per query than the fail threshold configured in guardrails.

Common situations: Queries filtering on many indexed columns at once in a large cluster with many SSTables; thresholds lowered for resource protection; after bulk loading, many small SSTables multiply referenced index counts.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/index/sai/plan/QueryController.java:357

    void maybeTriggerGuardrails(QueryViewBuilder.QueryView queryView)
    {
        int referencedIndexes = 0;

        // We want to make sure that no individual column expression touches too many SSTable-attached indexes:
        for (QueryViewBuilder.QueryExpressionView expressionSSTables : queryView.view)
            referencedIndexes = Math.max(referencedIndexes, expressionSSTables.sstableIndexes.size());

        if (Guardrails.saiSSTableIndexesPerQuery.failsOn(referencedIndexes, null))
        {
            String msg = String.format("Query %s attempted to read from too many indexes (%s) but max allowed is %s; " +
                                       "query aborted (see sai_sstable_indexes_per_query_fail_threshold)",
                                       command.toCQLString(),
                                       referencedIndexes,
                                       Guardrails.CONFIG_PROVIDER.getOrCreate(null).getSaiSSTableIndexesPerQueryFailThreshold());
            Tracing.trace(msg);
            MessageParams.add(ParamType.TOO_MANY_REFERENCED_INDEXES_FAIL, referencedIndexes);
            throw new QueryReferencingTooManyIndexesException(msg);
        }
        else if (Guardrails.saiSSTableIndexesPerQuery.warnsOn(referencedIndexes, null))
        {
            MessageParams.add(ParamType.TOO_MANY_REFERENCED_INDEXES_WARN, referencedIndexes);
        }
    }

    /**
     * Returns whether this query is not selecting the {@link PrimaryKey}.
     * The query does not select the key if both of the following statements are false:
     *  1. The table associated with the query is not using clustering keys
     *  2. The clustering index filter for the command wants the row.
     * <p>
     *  Item 2 is important in paged queries where the {@link org.apache.cassandra.db.filter.ClusteringIndexSliceFilter} for
     *  subsequent paged queries may not select rows that are returned by the index
     *  search because that is initially partition based.
     *
     * @param key The {@link PrimaryKey} to be tested

View on GitHub (pinned to 88fd0f6a0e)