apache/cassandra · error · InvalidRequestException
Counter columns cannot be accessed within a transaction;
Error message
Counter columns cannot be accessed within a transaction; %s statement %s
What it means
Counter tables cannot be read (or written) inside Accord transactions; the transaction engine does not support counter columns. For SELECTs, TransactionStatement.validate(SelectStatement) throws when prepared.table.isCounter().
Solutions
- Move counter reads/writes out of the transaction
- Migrate to non-counter columns (e.g., plain longs with CAS or a txn-managed value) if atomic combined semantics are needed
- Restructure the schema so counters and transactional data use separate tables and separate code paths
Example fix
// before BEGIN TRANSACTION SELECT c FROM counter_t WHERE pk = 1; COMMIT; // after SELECT c FROM counter_t WHERE pk = 1; // outside any transaction
Defensive patterns
Strategy: validation
Validate before calling
TableMetadata t = cluster.getMetadata().getKeyspace(ks).getTable(table); if (t.getOptions().getCounter()) throw new IllegalStateException("counters cannot be used in transactions: " + table); Try / catch
try { session.execute(txnCql); } catch (InvalidRequestException e) { if (e.getMessage().contains("Counter columns cannot be accessed within a transaction")) { /* route to non-transactional path */ } else throw e; } Prevention
- Keep counter tables outside transaction code paths
- Migrate counters to regular columns if transactional semantics are required
- Document per-table capability (counter vs transactional) in schema ownership docs
When it happens
Trigger: A SELECT within BEGIN TRANSACTION ... COMMIT targets a COUNTER table.
Common situations: Mixing counter increment logic into a transaction; retrofitting a legacy counter table into Accord-based workflows.
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
- Accord transactions are disabled on table (See…
- Accord transactions are disabled on table (table is being…
- Cannot add a counter column to Accord table
- Cannot create table . with transactional mode with…
- Cannot drop keyspace
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/39d35848d981f5c5.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/cql3/statements/TransactionStatement.java:710
return false;
}
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,View on GitHub (pinned to 88fd0f6a0e)