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

  1. Issue one serial read per partition (loop over keys, one query each).
  2. Drop the serial consistency for the multi-partition read if linearizability across partitions is not required.
  3. 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

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


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