{"record":{"id":"610b58d580e66778","repo":"apache/cassandra","slug":"metadata-only-supports-single-partition-key-qu","errorCode":null,"errorMessage":"metadata + \" only supports single partition key queries\"","messagePattern":"metadata \\+ \" only supports single partition key queries\"","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/virtual/AccordDebugKeyspace.java","lineNumber":2136,"sourceCode":"\n    static abstract class AbstractTxnGraphTable extends AbstractLazyVirtualTable\n    {\n        protected AbstractTxnGraphTable(TableMetadata metadata, OnTimeout onTimeout, Sorted sorted)\n        {\n            super(metadata, onTimeout, sorted);\n        }\n\n        protected AbstractTxnGraphTable(TableMetadata metadata, OnTimeout onTimeout, Sorted sorted, Sorted sortedByPartitionKey)\n        {\n            super(metadata, onTimeout, sorted, sortedByPartitionKey);\n        }\n\n        @Override\n        protected void collect(PartitionsCollector collector)\n        {\n            Object[] pks = collector.singlePartitionKey();\n            if (pks == null)\n                throw new InvalidRequestException(metadata + \" only supports single partition key queries\");\n\n            FilterRange<Integer> depthRange = collector.filters(\"depth\", Function.identity(), i -> i + 1, i -> i - 1);\n            int maxDepth = depthRange.max == null ? Integer.MAX_VALUE : depthRange.max;\n\n            // TODO (expected): cleanly handle Timestamp.NONE / Timestamp.MAX\n            FilterRange<String> executeAtRange = collector.filters(\"execute_at\", Function.identity(), i -> Timestamp.parse(i).next().toString(), i -> Timestamp.parse(i).prev().toString());\n            FilterRange<String> parentRange = collector.filters(\"parent\", Function.identity(), i -> Timestamp.parse(i).next().toString(), i -> Timestamp.parse(i).prev().toString());\n            Timestamp min = Timestamp.nonNullOrMax(Timestamp.nonNullOrMax(executeAtRange == null ? null : executeAtRange.min == null ? null : Timestamp.tryParse(executeAtRange.min), parentRange == null ? null : parentRange.min == null ? null : Timestamp.tryParse(parentRange.min)), Timestamp.NONE);\n\n\n            TxnKindsAndDomains kinds;\n            Participants<?> intersects;\n            {\n                TxnKindsAndDomains tmpKinds = TxnKindsAndDomains.ALL;\n                Participants<?> tmpIntersects = null;\n                for (RowFilter.Expression expr : collector.rowFilter().getExpressions())\n                {\n                    if (expr.isCustom())","sourceCodeStart":2118,"sourceCodeEnd":2154,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/virtual/AccordDebugKeyspace.java#L2118-L2154","documentation":"This accord debug virtual table (e.g. the txn-ops/journal dump table) implements collect() via collector.singlePartitionKey(), which returns non-null only when the query is restricted to exactly one partition key. Queries without a partition key constraint (full scans, or multi-partition IN queries) throw InvalidRequestException.","triggerScenarios":"Running `SELECT * FROM <table>;` or a multi-partition query against the accord debug table without a WHERE clause pinning the partition key (e.g. txn_id) to a single value.","commonSituations":"Exploratory browsing of the debug table without knowing a txn id; dashboards attempting full-table scans; assuming virtual tables support unrestricted reads.","solutions":["Add a WHERE clause that pins the partition key to a single value, e.g. `WHERE txn_id = '<txnId>'`.","Iterate over known txn ids client-side, issuing one single-partition query per id.","Use depth/execute_at filters only as additional constraints on top of the single-partition key."],"exampleFix":"// before\nSELECT * FROM system_views.accord_txn_ops;\n// after\nSELECT * FROM system_views.accord_txn_ops WHERE txn_id = '<txnId>';","handlingStrategy":"validation","validationCode":"// Enforce single-partition reads on accord debug tables\nString where = extractWhereClause(query);\nif (where == null || !where.matches(\".*txn_id\\s*=\\s*'[^']+'.*\"))\n    throw new IllegalArgumentException(\"accord debug tables require a single partition key equality predicate\");","typeGuard":null,"tryCatchPattern":"try {\n    session.execute(query);\n} catch (InvalidRequestException e) {\n    if (e.getMessage().contains(\"only supports single partition key queries\")) {\n        // rewrite the query with WHERE txn_id = '<id>'\n    }\n}","preventionTips":["Always include an equality predicate on the partition key when querying accord debug tables.","Never rely on full scans of these debug tables.","Iterate txn ids client-side issuing one single-partition query each."],"tags":["query-constraint","partition-key","virtual-table","accord-debug"],"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-17T15:17:12.973Z"}