{"record":{"id":"6e5c80a704c165ee","repo":"apache/cassandra","slug":"column-s-cannot-be-restricted-by-two-inequaliti","errorCode":null,"errorMessage":"Column \"%s\" cannot be restricted by two inequalities not starting with the same column","messagePattern":"Column \"(.+?)\" cannot be restricted by two inequalities not starting with the same column","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/restrictions/MergedRestriction.java","lineNumber":155,"sourceCode":"                    throw invalidRequest(Relation.FROZEN_MAP_ENTRY_PREDICATES_NOT_SUPPORTED, column.name);\n                }\n            }\n\n            throw invalidRequest(\"Collection column %s can only be restricted by CONTAINS, CONTAINS KEY, NOT_CONTAINS, NOT_CONTAINS_KEY\" +\n                                 \" or map-entry equality if it already restricted by one of those\",\n                                 restriction.firstColumn().name);\n        }\n\n        if (restriction.isSlice() && other.isSlice())\n        {\n            ColumnMetadata firstColumn = restriction.firstColumn();\n            ColumnMetadata otherFirstColumn = other.firstColumn();\n            if (!firstColumn.equals(otherFirstColumn))\n            {\n                ColumnMetadata column = firstColumn.position() > otherFirstColumn.position() ? firstColumn\n                                                                                             : otherFirstColumn;\n\n                throw invalidRequest(\"Column \\\"%s\\\" cannot be restricted by two inequalities not starting with the same column\",\n                                     column.name);\n            }\n\n            if ((restriction.operator() == Operator.GT || restriction.operator() == Operator.GTE || restriction.operator() == Operator.BETWEEN) &&\n                    (other.operator() == Operator.GT || other.operator() == Operator.GTE || other.operator() == Operator.BETWEEN))\n            {\n                throw invalidRequest(\"More than one restriction was found for the start bound on %s\",\n                                     toCQLString(getColumnsInCommons(restriction, other)));\n            }\n\n            if ((restriction.operator() == Operator.LT || restriction.operator() == Operator.LTE || restriction.operator() == Operator.BETWEEN) &&\n                    (other.operator() == Operator.LT || other.operator() == Operator.LTE || other.operator() == Operator.BETWEEN))\n            {\n                throw invalidRequest(\"More than one restriction was found for the end bound on %s\",\n                                     toCQLString(getColumnsInCommons(restriction, other)));\n            }\n        }\n    }","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/restrictions/MergedRestriction.java#L137-L173","documentation":"Cassandra throws this when merging two simple restrictions on the same column family because two inequality (>, >=, BETWEEN) restrictions exist whose leading column differs. Clustering-column ranges must form a single contiguous prefix; inequalities starting at different columns would make the slice bounds ambiguous, so Cassandra rejects the query at validation time.","triggerScenarios":"Issuing a CQL SELECT with two inequality restrictions on different clustering columns of the same primary key, e.g. WHERE clustering1 > 5 AND clustering2 >= 2 — MergedRestriction.validate() detects firstColumn() != other.firstColumn() and rejects.","commonSituations":"Users coming from SQL expect per-column range predicates to work; modeling time-series data with two clustering columns (e.g. day > X AND hour > Y) and forgetting Cassandra's clustering-prefix rules.","solutions":["Restructure the query so only one clustering column carries an inequality and all preceding clustering columns use EQ restrictions","Query without one of the inequality predicates and filter client-side","Change the table's clustering order (WITH CLUSTERING ORDER BY) or data model so the range column is a single clustering column","Use ALLOW FILTERING with a secondary index on the second column if the data set is small"],"exampleFix":"// before\nSELECT * FROM metrics WHERE day > '2026-01-01' AND hour >= 12;\n// after\nSELECT * FROM metrics WHERE day = '2026-01-01' AND hour >= 12;\n// or query one range column only:\nSELECT * FROM events WHERE ts > :start AND ts < :end;","handlingStrategy":"validation","validationCode":"// client-side pre-check before sending CQL\nconst ineqCols = predicates.filter(p => ['>','>='].includes(p.op)).map(p => p.column);\nif (new Set(ineqCols).size > 1) throw new Error('Only one clustering column may carry an inequality: ' + ineqCols);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Give each clustering prefix segment at most one range predicate","Use EQ for all clustering columns before the range column","Model time ranges on a single clustering column","Test dynamic query builders against Cassandra's clustering-prefix rules"],"tags":["cql","query-validation","clustering-columns"],"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-14T21:17:11.552Z"}