apache/cassandra · warning

Aggregation query used without partition key

Error message

Aggregation query used without partition key

What it means

When a query performs aggregation (COUNT, SUM, AVG, ...) without a partition key restriction, Cassandra must scan/aggregate across the whole table (or many partitions) on the coordinator. SelectStatement.execute warns the client and logs a rate-limited server warning because such queries can be extremely expensive.

Solutions

  1. Add a partition key restriction so aggregation is scoped to one partition
  2. Maintain denormalized counters/aggregate state instead of full-table COUNT
  3. Use analytics tooling (Spark) for full-table aggregation rather than CQL
  4. Suppress deliberately via guardrails/page-size config only for known-small tables

Example fix

// before
SELECT count(*) FROM sensor_data;
// after
SELECT count(*) FROM sensor_data WHERE device_id = ?;
Defensive patterns

Strategy: validation

Validate before calling

if (isAggregate(cql) && !cql.matches(".*WHERE\\s+.*=?")) {
    throw new IllegalArgumentException("aggregation without partition key restriction is forbidden");
}

Prevention

When it happens

Trigger: Running `SELECT count(*) FROM ks.tbl` or other aggregate with no WHERE clause on the partition key; also for token-range or secondary-index scans that lack partition-key restrictions.

Common situations: Ad-hoc analytics against production tables; COUNT(*) health checks on large tables; migrations from relational databases assuming free full-table aggregation.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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

Appendix: source

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

    private ResultMessage.Rows execute(QueryState state,
                                       Pager pager,
                                       QueryOptions options,
                                       Selectors selectors,
                                       int pageSize,
                                       long nowInSec,
                                       int userLimit,
                                       AggregationSpecification aggregationSpec,
                                       Dispatcher.RequestTime requestTime,
                                       boolean unmask)
    {
        Guardrails.pageSize.guard(pageSize, table(), false, state.getClientState());

        if (aggregationSpecFactory != null)
        {
            if (!restrictions.hasPartitionKeyRestrictions())
            {
                warn("Aggregation query used without partition key");
                noSpamLogger.warn(String.format("Aggregation query used without partition key on table %s.%s, aggregation type: %s",
                                                 keyspace(), table(), aggregationSpec.kind()));
            }
            else if (restrictions.keyIsInRelation())
            {
                warn("Aggregation query used on multiple partition keys (IN restriction)");
                noSpamLogger.warn(String.format("Aggregation query used on multiple partition keys (IN restriction) on table %s.%s, aggregation type: %s",
                                                 keyspace(), table(), aggregationSpec.kind()));
            }
        }

        // We can't properly do post-query ordering if we page (see #6722)
        // For GROUP BY or aggregation queries we always page internally even if the user has turned paging off
        checkFalse(pageSize > 0 && needsPostQueryOrdering(),
                  "Cannot page queries with both ORDER BY and a IN restriction on the partition key;"
                  + " you must either remove the ORDER BY or the IN and sort client side, or disable paging for this query");

        ResultMessage.Rows msg;

View on GitHub (pinned to 88fd0f6a0e)