apache/cassandra · warning

Top-K queries can only be run with consistency level ONE /…

Error message

Top-K queries can only be run with consistency level ONE / LOCAL_ONE / NODE_LOCAL. Consistency level %s was requested. Downgrading the consistency level to %s.

What it means

Top-K (vector ANN) queries only support consistency levels ONE / LOCAL_ONE / NODE_LOCAL. When a higher consistency level is requested, SelectStatement.execute silently downgrades it to LOCAL_ONE (if the requested level was datacenter-local) or ONE and warns the client.

Solutions

  1. Set consistency level ONE or LOCAL_ONE explicitly on ANN queries (e.g. driver withDefaultConsistencyLevel or per-query setConsistencyLevel)
  2. Use LOCAL_ONE for cross-DC deployments to keep reads local
  3. Separate ANN queries into a dedicated session/profile with the correct consistency profile

Example fix

// before
SimpleStatement q = SimpleStatement.builder("SELECT ... ORDER BY embedding ANN OF [0.1,0.2] LIMIT 5").build(); // default QUORUM
// after
SimpleStatement q = SimpleStatement.builder("SELECT ... ORDER BY embedding ANN OF [0.1,0.2] LIMIT 5")
    .setConsistencyLevel(ConsistencyLevel.LOCAL_ONE).build();
Defensive patterns

Strategy: validation

Validate before calling

if (isAnnQuery && cl != ConsistencyLevel.ONE && cl != ConsistencyLevel.LOCAL_ONE) {
    throw new IllegalArgumentException("ANN query requires ONE/LOCAL_ONE, got " + cl);
}

Prevention

When it happens

Trigger: Executing an ANN/Top-K SELECT (ORDER BY ... ANN OF vector) with consistency level QUORUM, LOCAL_QUORUM, THREE, EACH_QUORUM, ALL, etc.; the coordinator rewrites QueryOptions and warns via ClientWarn.

Common situations: Application sets a driver default consistency level of QUORUM/LOCAL_QUORUM and issues vector searches; code shared between normal reads and ANN reads; porting queries from non-vector workloads.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/cql3/statements/SelectStatement.java:405

        // Handle additional validation for topK queries
        if (restrictions.isTopK())
        {
            checkFalse(aggregationSpec != null, TOPK_AGGREGATION_ERROR);

            // We aren't going to allow SERIAL at all, so we can error out on those.
            checkFalse(options.getConsistency() == ConsistencyLevel.LOCAL_SERIAL ||
                       options.getConsistency() == ConsistencyLevel.SERIAL,
                       String.format(TOPK_CONSISTENCY_LEVEL_ERROR, options.getConsistency()));

            if (options.getConsistency().needsReconciliation())
            {
                ConsistencyLevel supplied = options.getConsistency();
                ConsistencyLevel downgrade = supplied.isDatacenterLocal() ? ConsistencyLevel.LOCAL_ONE : ConsistencyLevel.ONE;

                options = QueryOptions.withConsistencyLevel(options, downgrade);

                ClientWarn.instance.warn(String.format(TOPK_CONSISTENCY_LEVEL_WARNING, supplied, downgrade));
            }

            checkFalse(limit.isUnlimited(), TOPK_LIMIT_ERROR);

            checkFalse(limit.perPartitionCount() != DataLimits.NO_LIMIT, TOPK_PARTITION_LIMIT_ERROR);

            if (pageSize > 0 && pageSize < limit.count())
            {
                int oldPageSize = pageSize;
                pageSize = limit.count();
                limit = getDataLimits(userLimit, userPerPartitionLimit, pageSize, aggregationSpec);
                options = QueryOptions.withPageSize(options, pageSize);
                ClientWarn.instance.warn(String.format(TOPK_PAGE_SIZE_WARNING, oldPageSize, limit.count(), pageSize));
            }
        }

        ReadQuery query = getQuery(options, state.getClientState(), selectors.getColumnFilter(), nowInSec, limit, PotentialTxnConflicts.DISALLOW);

View on GitHub (pinned to 88fd0f6a0e)