apache/cassandra · error · InvalidRequestException
SERIAL/LOCAL_SERIAL consistency may only be requested for on
Error message
SERIAL/LOCAL_SERIAL consistency may only be requested for one partition at a time
What it means
InvalidRequestException from legacyReadWithPaxos: serial (LWT/Paxos) reads support only a single partition per request because Paxos rounds are per-partition. Passing a read group with more than one query is rejected before any protocol work starts.
Source
Thrown at src/java/org/apache/cassandra/service/StorageProxy.java:2353
List<PartitionIterator> partitionIterators = new ArrayList<>(numQueries);
for (int i = 0; i < numQueries; i++)
partitionIterators.add(null);
for (Map.Entry<Integer, TxnDataValue> e : data.entrySet())
{
int queryIndex = e.getKey();
TxnDataKeyValue value = ((TxnDataKeyValue)e.getValue());
partitionIterators.set(queryIndex, singletonIterator(value.rowIterator(isQueryReversed.test(queryIndex))));
}
return serialReadResult(partitionIterators.size() == 1 ? partitionIterators.get(0) : PartitionIterators.concat(partitionIterators));
}
}
private static ConsensusAttemptResult legacyReadWithPaxos(SinglePartitionReadCommand.Group group, ConsistencyLevel consistencyLevel, Dispatcher.RequestTime requestTime)
throws InvalidRequestException, UnavailableException, ReadFailureException, ReadTimeoutException
{
long start = nanoTime();
if (group.queries.size() > 1)
throw new InvalidRequestException("SERIAL/LOCAL_SERIAL consistency may only be requested for one partition at a time");
SinglePartitionReadCommand command = group.queries.get(0);
TableMetadata metadata = command.metadata();
DecoratedKey key = command.partitionKey();
// calculate the blockFor before repair any paxos round to avoid RS being altered in between.
int blockForRead = consistencyLevel.blockFor(Keyspace.open(metadata.keyspace).getReplicationStrategy());
try
{
final ConsistencyLevel consistencyForReplayCommitsOrFetch = consistencyLevel.isDatacenterLocal()
? ConsistencyLevel.LOCAL_QUORUM
: ConsistencyLevel.QUORUM;
try
{
// Commit an empty update to make sure all in-progress updates that should be finished first is, _and_
// that no other in-progress can get resurrected.
Function<Ballot, Pair<PartitionUpdate, RowIterator>> updateProposer =View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Issue one serial read per partition (loop over keys, one query each).
- Drop the serial consistency for the multi-partition read if linearizability across partitions is not required.
- Restructure the data model so the operations needing serial consistency fit in one partition.
Example fix
// before
// SELECT ... WHERE pk IN (?, ?) with consistency SERIAL
// after
for (Object pk : keys) {
SimpleStatement st = SimpleStatement.builder("SELECT * FROM ks.t WHERE pk=?").setPositionalArgs(pk)
.setSerialConsistencyLevel(ConsistencyLevel.SERIAL).build();
session.execute(st);
} Defensive patterns
Strategy: validation
Validate before calling
if (keys.size() > 1 && serialConsistency) {
throw new IllegalArgumentException("SERIAL reads must target a single partition");
} Try / catch
catch (InvalidRequestException e) {
if (e.getMessage().contains("one partition at a time")) {
return keys.stream().map(k -> executeSerialRead(k)).collect(toList());
}
throw e;
} Prevention
- Never use IN/multi-partition selects with SERIAL/LOCAL_SERIAL consistency.
- Build driver statements one partition per serial read.
- Design LWT partitions so transactional needs fit one partition.
- Add a unit test asserting serial reads use a single partition key.
When it happens
Trigger: Issuing a SERIAL or LOCAL_SERIAL read whose SinglePartitionReadCommand.Group contains >1 query — i.e., a serial read that spans multiple partitions (e.g., multi-partition IN clause read with serial consistency through StorageProxy.read with serial consistency level).
Common situations: Driver-built batched/multi-partition SELECT with consistency SERIAL; migrating thrift-era multi-get to serial reads; IN queries on the partition key with SERIAL consistency.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- ReadTimeoutException(consistency=%s, received=0, blockFor=%s
- paxos_cache_size option was set incorrectly to '<value>', su
- Invalid empty serial consistency level
- You must use conditional updates for serializable writes
- this + " is not supported as conditional update commit consi
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/0b0329b503297af2.
Report an issue: GitHub.