{"record":{"id":"b8de0ffc784351a8","repo":"apache/cassandra","slug":"must-specify-full-partition-key-bounds-for-the-und","errorCode":null,"errorMessage":"Must specify full partition key bounds for the underlying table","messagePattern":"Must specify full partition key bounds for the underlying table","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/virtual/RemoteToLocalVirtualTable.java","lineNumber":388,"sourceCode":"        for (RowFilter.Expression in : rowFilter.getExpressions())\n        {\n            RowFilter.Expression out = in.rebind(local);\n            if (out != null)\n                result.add(out);\n        }\n        return result;\n    }\n\n    private List<Request> rebind(TableMetadata local, Slice slice, boolean reversed, RowFilter rowFilter, ColumnFilter columnFilter)\n    {\n        ClusteringBound<?> start = slice.start();\n        ClusteringBound<?> end = slice.end();\n        int pkCount = local.partitionKeyColumns().size();\n        // TODO (expected): we can filter by partition key by inserting a new row filter, but need to impose ALLOW FILTERING restrictions\n        if (((start.size() > 0 && start.size() < pkCount) || (end.size() > 0 && end.size() < pkCount)))\n        {\n            if (!allowFilteringLocalPartitionKeysImplicitly)\n                throw new InvalidRequestException(\"Must specify full partition key bounds for the underlying table\");\n\n            List<ColumnMetadata> pks = local.partitionKeyColumns();\n            ByteBuffer[] starts = start.getBufferArray();\n            ByteBuffer[] ends = end.getBufferArray();\n\n            int minCount = Math.min(start.size(), end.size());\n            int maxCount = Math.max(start.size(), end.size());\n            int commonPrefixLength = 0;\n            while (commonPrefixLength < minCount && equalPart(start, end, commonPrefixLength))\n                ++commonPrefixLength;\n\n            RowFilter commonRowFilter = rowFilter;\n            if (commonPrefixLength > 0)\n            {\n                commonRowFilter = copy(commonRowFilter);\n                for (int i = 0 ; i < commonPrefixLength ; ++i)\n                    commonRowFilter.add(pks.get(i), Operator.EQ, starts[i]);\n            }","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/virtual/RemoteToLocalVirtualTable.java#L370-L406","documentation":"rebind() translates the virtual table's clustering bounds into a row filter on the underlying remote table. If the partition key bounds on the underlying table are partial (greater than 0 but fewer columns than the full partition key) and implicit ALLOW FILTERING is not enabled, the translation cannot produce an efficient scan and throws InvalidRequestException.","triggerScenarios":"SELECT that restricts only some columns of the underlying table's partition key within the WHERE clause (start.size() > 0 && < pkCount, or same for end) while the remote translation does not permit partial PK filtering.","commonSituations":"Queries ported from the base table where partial partition key restrictions plus ALLOW FILTERING were allowed; multi-column partition keys in the underlying table restricted on only the first column.","solutions":["Restrict on ALL partition key columns of the underlying table (full equality/range on every PK column).","Remove the partial PK restriction and filter client-side after fetching.","Enable the internal flag allowFilteringLocalPartitionKeysImplicitly if this usage is intended and acceptable performance-wise.","Add ALLOW FILTERING semantics at the base-table level if querying the underlying table directly."],"exampleFix":"// before\nSELECT * FROM vt WHERE pk_col1 = 'a';  -- pk has 2 columns\n// after\nSELECT * FROM vt WHERE pk_col1 = 'a' AND pk_col2 = 42;","handlingStrategy":"validation","validationCode":"// Ensure all partition key columns of the underlying table are restricted\nint pkCount = underlyingTable.partitionKeyColumns().size();\nif (restrictedPkColumns.size() > 0 && restrictedPkColumns.size() < pkCount)\n    throw new IllegalArgumentException(\"Must restrict all \" + pkCount + \" partition key columns\");","typeGuard":null,"tryCatchPattern":"try { session.execute(query); }\ncatch (InvalidRequestException e) {\n    if (e.getMessage().contains(\"full partition key bounds\"))\n        // rewrite query with complete PK restriction or filter client-side\n}\n","preventionTips":["Always restrict all partition key columns of the underlying table","Avoid porting ALLOW FILTERING queries from base tables to virtual tables","Filter remaining dimensions client-side","Check partition key column count of the underlying schema when writing queries"],"tags":["cassandra","virtual-table","partition-key","allow-filtering"],"backgroundTag":"missing-required-argument","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"}