apache/cassandra · error · InvalidRequestException
Within a transaction, SELECT statements must select a single
Error message
Within a transaction, SELECT statements must select a single partition; found <N> partitions
What it means
Within a transaction (TransactionStatement), every SELECT must resolve to exactly one partition. createNamedRead casts the select's query to a SinglePartitionReadQuery.Group and throws InvalidRequestException when the group contains more than one partition read command, because transactional reads must target a single partition key.
Source
Thrown at src/java/org/apache/cassandra/cql3/statements/TransactionStatement.java:278
return stream.iterator();
};
}
@Override
public ResultSet.ResultMetadata getResultMetadata()
{
return resultMetadata;
}
TxnNamedRead createNamedRead(NamedSelect namedSelect, QueryOptions options, TableMetadatasAndKeys.KeyCollector keyCollector)
{
SelectStatement select = namedSelect.select;
// We reject reads from both LET and SELECT that do not specify a single row.
@SuppressWarnings("unchecked")
SinglePartitionReadQuery.Group<SinglePartitionReadCommand> selectQuery = (SinglePartitionReadQuery.Group<SinglePartitionReadCommand>) select.getQuery(options, 0);
if (selectQuery.queries.size() != 1)
throw invalidRequest("Within a transaction, SELECT statements must select a single partition; found " + selectQuery.queries.size() + " partitions");
SinglePartitionReadCommand command = Iterables.getOnlyElement(selectQuery.queries);
return new TxnNamedRead(namedSelect.name, keyCollector.collect(command.metadata(), command.partitionKey()), command, keyCollector.tables);
}
List<TxnNamedRead> createNamedReads(NamedSelect namedSelect, QueryOptions options, TableMetadatasAndKeys.KeyCollector keyCollector)
{
SelectStatement select = namedSelect.select;
// We reject reads from both LET and SELECT that do not specify a single row.
@SuppressWarnings("unchecked")
SinglePartitionReadQuery.Group<SinglePartitionReadCommand> selectQuery = (SinglePartitionReadQuery.Group<SinglePartitionReadCommand>) select.getQuery(options, 0);
if (selectQuery.queries.size() == 1)
return Collections.singletonList(new TxnNamedRead(namedSelect.name, keyCollector.collect(select.table, selectQuery.queries.get(0).partitionKey()), selectQuery.queries.get(0), keyCollector.tables));
List<TxnNamedRead> list = new ArrayList<>(selectQuery.queries.size());
for (int i = 0; i < selectQuery.queries.size(); i++)
{View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Add an equality predicate on the full partition key to the transaction's SELECT
- Remove IN clauses spanning multiple partition keys; issue one transaction per partition
- Restructure the workload so each transaction reads rows from a single partition
Example fix
// before SELECT * FROM t WHERE pk IN (1, 2); -- within transaction: 2 partitions // after SELECT * FROM t WHERE pk = 1; -- single partition
Defensive patterns
Strategy: validation
Validate before calling
// ensure the WHERE clause pins the partition key before running a transaction
boolean singlePartition = whereClause.matches(".*pk\s*=\s*[^I].*") && !whereClause.toUpperCase().contains(" IN ");
if (!singlePartition) throw new IllegalArgumentException("transactional SELECT must target one partition"); Try / catch
try { session.execute(txnStatement); }
catch (InvalidRequestException e) { if (e.getMessage().contains("single partition")) { /* split into per-partition transactions */ } } Prevention
- Always include full partition-key equality in transactional SELECTs
- Avoid IN on partition keys inside transactions
- One transaction per partition
When it happens
Trigger: Running a transaction whose named SELECT (via LET or SELECT) has WHERE clauses that do not constrain the read to a single partition — e.g. missing the partition key equality predicate or using IN across multiple partition keys.
Common situations: Omitting the full primary key from the WHERE clause; using IN with multiple partition keys in a transactional SELECT; using ALLOW FILTERING-style ranges inside a transaction.
Understand the failure class
Background: "Invalid query parameter" / "Failed to parse value of ...": fixing bad query string parameters across APIs — this error's family across 36 libraries.
Related errors
- Key may not be empty
- Key may not be empty
- Key length of %d is longer than maximum of %d
- Transaction contains multiple updates to the same key and fi
- No ORDER BY clause allowed within a transaction; %s statemen
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/a7452f46a082c1d1.
Report an issue: GitHub.