apache/cassandra · error · InvalidRequestException
Batch with conditions cannot span multiple partitions
Error message
Batch with conditions cannot span multiple partitions
What it means
Conditional (LWT) batches in newer Cassandra versions must operate on a single partition: all statements' partition keys must be identical, since Paxos coordination is per-partition. In makeCasRequest, when collected partition keys differ, an InvalidRequestException is thrown naming the multi-partition violation.
Source
Thrown at src/java/org/apache/cassandra/cql3/statements/BatchStatement.java:631
CQL3CasRequest casRequest = null;
Set<ColumnMetadata> columnsWithConditions = new LinkedHashSet<>();
for (int i = 0; i < statements.size(); i++)
{
ModificationStatement statement = statements.get(i);
QueryOptions statementOptions = options.forStatement(i);
long timestamp = attrs.getTimestamp(batchTimestamp, statementOptions);
List<ByteBuffer> pks = statement.buildPartitionKeyNames(statementOptions, state.getClientState());
if (statement.getRestrictions().keyIsInRelation())
throw new IllegalArgumentException("Batch with conditions cannot span multiple partitions (you cannot use IN on the partition key)");
if (key == null)
{
key = statement.metadata().partitioner.decorateKey(pks.get(0));
casRequest = new CQL3CasRequest(statement.metadata(), key, conditionColumns, updatesRegularRows, updatesStaticRow, requestTime);
}
else if (!key.getKey().equals(pks.get(0)))
{
throw new InvalidRequestException("Batch with conditions cannot span multiple partitions");
}
checkFalse(statement.getRestrictions().clusteringKeyRestrictionsHasIN(),
"IN on the clustering key columns is not supported with conditional %s",
statement.type.isUpdate()? "updates" : "deletions");
if (statement.hasSlices())
{
// All of the conditions require meaningful Clustering, not Slices
assert !statement.hasConditions();
Slices slices = statement.createSlices(statementOptions);
// If all the ranges were invalid we do not need to do anything.
if (slices.isEmpty())
continue;
for (Slice slice : slices)
{View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Restructure the conditional batch so every statement targets the same partition key
- Move cross-partition conditional logic into the application (read-check-write with retries) or use a single-row/denormalized design
- If multi-partition atomicity is essential, consider a different data model or an external coordination mechanism
Example fix
// before
BEGIN BATCH UPDATE t SET v=1 WHERE pk=1 IF v=0;
UPDATE t SET v=2 WHERE pk=2 IF v=0; APPLY BATCH;
// after
BEGIN BATCH UPDATE t SET v=1 WHERE pk=1 IF v=0;
UPDATE t SET v=2 WHERE pk=1 IF v=0; APPLY BATCH;
Defensive patterns
Strategy: validation
Validate before calling
if (batchHasConditions && stmts.stream().map(s -> s.partitionKey()).distinct().count() > 1)
throw new IllegalArgumentException("LWT batch must target a single partition"); Try / catch
catch (InvalidRequestException e) { if (e.getMessage().contains("cannot span multiple partitions")) { splitPerPartitionAndRetry(); } else throw e; } Prevention
- Group conditional statements by partition key before batching
- Model data so conditionally-updated rows share a partition when atomicity is needed
When it happens
Trigger: A conditional batch (BEGIN BATCH ... IF) whose statements touch rows in two or more partitions — e.g. 'UPDATE t SET v=1 WHERE pk=1 IF x=1; UPDATE t SET v=2 WHERE pk=2 IF y=1'.
Common situations: Applications treating LWT batches as multi-row transactions across partitions; relational-style transaction porting; clustering-key writes accidentally using different partition key values.
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
- Cannot provide custom timestamp for conditional BATCH
- Conditional BATCH statements cannot include mutations for vi
- Batch with conditions cannot span multiple tables: %s
- Invalid empty serial consistency level
- Global TTL on the BATCH statement is not supported.
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/b18584e54b6291fc.
Report an issue: GitHub.