{"record":{"id":"a7452f46a082c1d1","repo":"apache/cassandra","slug":"within-a-transaction-select-statements-must-selec","errorCode":null,"errorMessage":"Within a transaction, SELECT statements must select a single partition; found <N> partitions","messagePattern":"Within a transaction, SELECT statements must select a single partition; found <N> partitions","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/statements/TransactionStatement.java","lineNumber":278,"sourceCode":"            return stream.iterator();\n        };\n    }\n\n    @Override\n    public ResultSet.ResultMetadata getResultMetadata()\n    {\n        return resultMetadata;\n    }\n\n    TxnNamedRead createNamedRead(NamedSelect namedSelect, QueryOptions options, TableMetadatasAndKeys.KeyCollector keyCollector)\n    {\n        SelectStatement select = namedSelect.select;\n        // We reject reads from both LET and SELECT that do not specify a single row.\n        @SuppressWarnings(\"unchecked\")\n        SinglePartitionReadQuery.Group<SinglePartitionReadCommand> selectQuery = (SinglePartitionReadQuery.Group<SinglePartitionReadCommand>) select.getQuery(options, 0);\n\n        if (selectQuery.queries.size() != 1)\n            throw invalidRequest(\"Within a transaction, SELECT statements must select a single partition; found \" + selectQuery.queries.size() + \" partitions\");\n\n        SinglePartitionReadCommand command = Iterables.getOnlyElement(selectQuery.queries);\n        return new TxnNamedRead(namedSelect.name, keyCollector.collect(command.metadata(), command.partitionKey()), command, keyCollector.tables);\n    }\n\n    List<TxnNamedRead> createNamedReads(NamedSelect namedSelect, QueryOptions options, TableMetadatasAndKeys.KeyCollector keyCollector)\n    {\n        SelectStatement select = namedSelect.select;\n        // We reject reads from both LET and SELECT that do not specify a single row.\n        @SuppressWarnings(\"unchecked\")\n        SinglePartitionReadQuery.Group<SinglePartitionReadCommand> selectQuery = (SinglePartitionReadQuery.Group<SinglePartitionReadCommand>) select.getQuery(options, 0);\n\n        if (selectQuery.queries.size() == 1)\n            return Collections.singletonList(new TxnNamedRead(namedSelect.name, keyCollector.collect(select.table, selectQuery.queries.get(0).partitionKey()), selectQuery.queries.get(0), keyCollector.tables));\n\n        List<TxnNamedRead> list = new ArrayList<>(selectQuery.queries.size());\n        for (int i = 0; i < selectQuery.queries.size(); i++)\n        {","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/statements/TransactionStatement.java#L260-L296","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nSELECT * FROM t WHERE pk IN (1, 2); -- within transaction: 2 partitions\n// after\nSELECT * FROM t WHERE pk = 1; -- single partition","handlingStrategy":"validation","validationCode":"// ensure the WHERE clause pins the partition key before running a transaction\nboolean singlePartition = whereClause.matches(\".*pk\\s*=\\s*[^I].*\") && !whereClause.toUpperCase().contains(\" IN \");\nif (!singlePartition) throw new IllegalArgumentException(\"transactional SELECT must target one partition\");","typeGuard":null,"tryCatchPattern":"try { session.execute(txnStatement); }\ncatch (InvalidRequestException e) { if (e.getMessage().contains(\"single partition\")) { /* split into per-partition transactions */ } }","preventionTips":["Always include full partition-key equality in transactional SELECTs","Avoid IN on partition keys inside transactions","One transaction per partition"],"tags":["cql","transactions","partition-key","validation"],"backgroundTag":"invalid-query-parameter","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"}