apache/cassandra · error · InvalidRequestException

No aggregation functions allowed within a transaction;

Error message

No aggregation functions allowed within a transaction; %s statement %s

What it means

Aggregate functions (count, sum, avg, ...) are not permitted in SELECTs inside Accord transactions. TransactionStatement.validate(SelectStatement) calls prepared.hasAggregation() and rejects the statement.

Solutions

  1. Remove aggregate functions from the in-transaction SELECT
  2. Read raw rows in the transaction and compute aggregates in the application
  3. Issue the aggregating query outside the transaction

Example fix

// before
BEGIN TRANSACTION SELECT count(*) FROM t WHERE pk = 1; COMMIT;
// after
BEGIN TRANSACTION SELECT v FROM t WHERE pk = 1; COMMIT; // count client-side
Defensive patterns

Strategy: validation

Validate before calling

java.util.regex.Pattern p = java.util.regex.Pattern.compile("\\b(count|sum|avg|min|max)\\s*\\(", java.util.regex.Pattern.CASE_INSENSITIVE); if (p.matcher(query).find() && inTransaction) throw new IllegalArgumentException("aggregation not allowed in transaction");

Try / catch

try { session.execute(txnCql); } catch (InvalidRequestException e) { if (e.getMessage().contains("No aggregation functions allowed within a transaction")) { /* compute aggregates client-side */ } else throw e; }

Prevention

When it happens

Trigger: A SELECT in BEGIN TRANSACTION ... COMMIT uses an aggregate function like count(*), sum(col), or a user-defined aggregate.

Common situations: Porting reporting queries into a transaction expecting consistent aggregate reads.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/cql3/statements/TransactionStatement.java:712

    private static void validate(SelectStatement.RawStatement select)
    {
        if (select.parameters.orderings != null && !select.parameters.orderings.isEmpty())
            throw invalidRequest(NO_ORDER_BY_IN_TXNS_MESSAGE, "SELECT", select.source);
        if (select.parameters.groups != null && !select.parameters.groups.isEmpty())
            throw invalidRequest(NO_GROUP_BY_IN_TXNS_MESSAGE, "SELECT", select.source);
    }

    private static void validate(SelectStatement prepared)
    {
        if (!prepared.table.isAccordEnabled())
            throw invalidRequest(TRANSACTIONS_DISABLED_ON_TABLE_MESSAGE, "SELECT", prepared.source);
        if (prepared.table.params.pendingDrop)
            throw invalidRequest(TRANSACTIONS_DISABLED_ON_TABLE_BEING_DROPPED_MESSAGE, "SELECT", prepared.source);
        if (prepared.table.isCounter())
            throw invalidRequest(NO_COUNTERS_IN_TXNS_MESSAGE, "SELECT", prepared.source);
        if (prepared.hasAggregation())
            throw invalidRequest(NO_AGGREGATION_IN_TXNS_MESSAGE, "SELECT", prepared.source);

        // when "LIMIT ?" this check can't be performed, so need to do again once the options are known
        if (prepared.getRestrictions().keyIsInRelation())
            checkTrue(prepared.isLimitMarker() || prepared.getLimit(null) == DataLimits.NO_LIMIT, NO_PARTITION_IN_CLAUSE_WITH_LIMIT, "SELECT", prepared.source);
    }

    public static class Parsed extends QualifiedStatement.Composite
    {
        private final List<SelectStatement.RawStatement> assignments;
        private final SelectStatement.RawStatement select;
        private final List<RowDataReference.Raw> returning;
        private final List<ModificationStatement.Parsed> updates;
        private final List<ConditionStatement.Raw> conditions;
        private final List<RowDataReference.Raw> dataReferences;

        public Parsed(List<SelectStatement.RawStatement> assignments,
                      SelectStatement.RawStatement select,
                      List<RowDataReference.Raw> returning,

View on GitHub (pinned to 88fd0f6a0e)