{"record":{"id":"47e298510f1e808d","repo":"apache/cassandra","slug":"no-group-by-clause-allowed-within-a-transaction","errorCode":null,"errorMessage":"No GROUP BY clause allowed within a transaction; %s statement %s","messagePattern":"No GROUP BY clause allowed within a transaction; (.+?) statement (.+?)","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/statements/TransactionStatement.java","lineNumber":700,"sourceCode":"    @Override\n    public AuditLogContext getAuditLogContext()\n    {\n        return new AuditLogContext(AuditLogEntryType.TRANSACTION);\n    }\n\n    @Override\n    public boolean eligibleAsPreparedStatement()\n    {\n        // false is the default, but still best to be explicit.\n        return false;\n    }\n\n    private static void validate(SelectStatement.RawStatement select)\n    {\n        if (select.parameters.orderings != null && !select.parameters.orderings.isEmpty())\n            throw invalidRequest(NO_ORDER_BY_IN_TXNS_MESSAGE, \"SELECT\", select.source);\n        if (select.parameters.groups != null && !select.parameters.groups.isEmpty())\n            throw invalidRequest(NO_GROUP_BY_IN_TXNS_MESSAGE, \"SELECT\", select.source);\n    }\n\n    private static void validate(SelectStatement prepared)\n    {\n        if (!prepared.table.isAccordEnabled())\n            throw invalidRequest(TRANSACTIONS_DISABLED_ON_TABLE_MESSAGE, \"SELECT\", prepared.source);\n        if (prepared.table.params.pendingDrop)\n            throw invalidRequest(TRANSACTIONS_DISABLED_ON_TABLE_BEING_DROPPED_MESSAGE, \"SELECT\", prepared.source);\n        if (prepared.table.isCounter())\n            throw invalidRequest(NO_COUNTERS_IN_TXNS_MESSAGE, \"SELECT\", prepared.source);\n        if (prepared.hasAggregation())\n            throw invalidRequest(NO_AGGREGATION_IN_TXNS_MESSAGE, \"SELECT\", prepared.source);\n\n        // when \"LIMIT ?\" this check can't be performed, so need to do again once the options are known\n        if (prepared.getRestrictions().keyIsInRelation())\n            checkTrue(prepared.isLimitMarker() || prepared.getLimit(null) == DataLimits.NO_LIMIT, NO_PARTITION_IN_CLAUSE_WITH_LIMIT, \"SELECT\", prepared.source);\n    }\n","sourceCodeStart":682,"sourceCodeEnd":718,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/statements/TransactionStatement.java#L682-L718","documentation":"SELECT statements with a GROUP BY clause are not allowed inside Accord transactions. Transactional reads do not support aggregation grouping, so TransactionStatement.validate(SelectStatement.RawStatement) throws when select.parameters.groups is non-empty.","triggerScenarios":"A SELECT within BEGIN TRANSACTION ... COMMIT on an Accord-enabled table contains `GROUP BY <column>`; detected alongside the ORDER BY check in the raw-statement validate path.","commonSituations":"Wrapping analytical/aggregating queries in a transaction to get consistent reads; auto-generated CQL that always emits GROUP BY.","solutions":["Remove the GROUP BY clause from the in-transaction SELECT","Fetch raw rows in the transaction and group/aggregate client-side","Run the aggregating query outside the transaction"],"exampleFix":"// before\nBEGIN TRANSACTION\n  SELECT k, count(v) FROM t WHERE pk = 1 GROUP BY k;\nCOMMIT TRANSACTION;\n// after\nBEGIN TRANSACTION\n  SELECT k, v FROM t WHERE pk = 1;\nCOMMIT TRANSACTION; // aggregate in application","handlingStrategy":"validation","validationCode":"if (query.toUpperCase().matches(\"(?s).*GROUP\\\\s+BY.*\") && inTransaction) throw new IllegalArgumentException(\"GROUP BY not allowed in transaction\");","typeGuard":null,"tryCatchPattern":"try { session.execute(txnCql); } catch (InvalidRequestException e) { if (e.getMessage().contains(\"No GROUP BY clause allowed within a transaction\")) { /* remove GROUP BY, aggregate client-side */ } else throw e; }","preventionTips":["Never wrap analytical/aggregating queries in transactions","Aggregate in the application after reading raw rows","Add CQL linter rules for transaction blocks"],"tags":["cql","transactions","accord","validation"],"backgroundTag":"unsupported-operation","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}