{"record":{"id":"5c8e9b3ec7321566","repo":"apache/cassandra","slug":"serial-local-serial-consistency-may-only-be-reques-5c8e9b","errorCode":null,"errorMessage":"SERIAL/LOCAL_SERIAL consistency may only be requested for one partition at a time","messagePattern":"SERIAL/LOCAL_SERIAL consistency may only be requested for one partition at a time","errorType":"exception","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/service/paxos/Paxos.java","lineNumber":895,"sourceCode":"\n            casWriteMetrics.addNano(latency);\n            writeMetricsMap.get(consistencyForConsensus).addNano(latency);\n        }\n    }\n\n    private static RowIterator conditionNotMet(FilteredPartition read)\n    {\n        Tracing.trace(\"CAS precondition rejected\", read);\n        casWriteMetrics.conditionNotMet.inc();\n        return read.rowIterator(false);\n    }\n\n    public static ConsensusAttemptResult read(SinglePartitionReadCommand.Group group, ConsistencyLevel consistencyForConsensus, Dispatcher.RequestTime requestTime, long minHLC)\n            throws InvalidRequestException, UnavailableException, ReadFailureException, ReadTimeoutException\n    {\n        long start = nanoTime();\n        if (group.queries.size() > 1)\n            throw new InvalidRequestException(\"SERIAL/LOCAL_SERIAL consistency may only be requested for one partition at a time\");\n        long deadline = requestTime.computeDeadline(DatabaseDescriptor.getReadRpcTimeout(NANOSECONDS));\n\n        int failedAttemptsDueToContention = 0;\n        Ballot minimumBallot = Ballot.atUnixMicrosWithLsb(minHLC, 0, GLOBAL);\n        SinglePartitionReadCommand read = group.queries.get(0);\n        // Allow potential txn conflicts since Paxos will manage them\n        read = read.withTransactionalSettings(false, read.nowInSec());\n        try (PaxosOperationLock lock = PaxosState.lock(read.partitionKey(), read.metadata(), deadline, consistencyForConsensus, false))\n        {\n            while (true)\n            {\n                // does the work of applying in-progress writes; throws UAE or timeout if it can't\n                final BeginResult begin = begin(deadline, read, consistencyForConsensus, false, minimumBallot, failedAttemptsDueToContention, requestTime);\n                failedAttemptsDueToContention = begin.failedAttemptsDueToContention;\n\n                if (begin.retryWithNewConsenusProtocol)\n                {\n                    casReadMetrics.beginMigrationRejects.mark();","sourceCodeStart":877,"sourceCodeEnd":913,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/service/paxos/Paxos.java#L877-L913","documentation":"Paxos serial (LWT) operations operate on exactly one partition per protocol round. When a serial read is issued as a group containing more than one partition query, Cassandra rejects it with this InvalidRequestException because a single Paxos round cannot cover multiple partitions.","triggerScenarios":"Executing a batched/multi-partition SELECT with consistency SERIAL or LOCAL_SERIAL (e.g. a batch containing LWT conditions on multiple partitions, or a partition-range/multi-partition read command group issued with serial consistency).","commonSituations":"Application batches mixing conditional writes across partitions; drivers issuing multi-partition reads with serial consistency after a refactor; ORMs generating multi-row serial queries; misuse of serial consistency on non-single-partition SELECTs.","solutions":["Restructure the operation so each serial read/write targets a single partition (one Paxos round per partition)","Use light-weight transactions only on single-partition queries; for multi-partition atomicity move to Accord transactions or redesign the data model","Remove SERIAL/LOCAL_SERIAL from multi-partition reads if serial semantics aren't needed — use plain quorum reads","Split the batch into per-partition statements executed separately"],"exampleFix":"// before: multi-partition serial read\nselect = select().serialConsistency(SERIAL); // group of 2 partitions\n// after: per-partition serial reads\nfor (cmd : queries) execute(cmd.bind(partition).serialConsistency(SERIAL));","handlingStrategy":"validation","validationCode":"// only set serial consistency for single-partition statements\nif (statementQueriesSinglePartition(stmt)) stmt.setSerialConsistency(ConsistencyLevel.SERIAL);","typeGuard":null,"tryCatchPattern":"try { session.execute(stmt); }\ncatch (InvalidRequestException e) { /* split into per-partition statements without serial consistency on groups */ }","preventionTips":["Use LWT/SERIAL only on single-partition queries","Do not mix conditional writes on multiple partitions in one batch","Redesign multi-partition atomicity needs around Accord transactions or denormalization"],"tags":["paxos","lwt","invalid-request","batch"],"backgroundTag":"invalid-argument-value","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}