{"record":{"id":"9d239fc96ce65325","repo":"apache/cassandra","slug":"s-cannot-be-used-with-s-relations","errorCode":null,"errorMessage":"%s cannot be used with %s relations","messagePattern":"(.+?) cannot be used with (.+?) relations","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/Operator.java","lineNumber":978,"sourceCode":"    List<ByteBuffer> unpackMultiCellElements(MultiElementType<?> type, ByteBuffer value)\n    {\n        checkTrue(value != null, \"Invalid comparison with null for operator \\\"%s\\\"\", this);\n        List<ByteBuffer> elements = type.unpack(value);\n        if (type.isCollection() && elements.isEmpty())\n            throw  invalidRequest(\"Invalid comparison with an empty %s for operator \\\"%s\\\"\", ((CollectionType<?>) type).kind, this);\n        return elements;\n    }\n\n    public static int serializedSize()\n    {\n        return 4;\n    }\n\n    public void validateFor(ColumnsExpression expression)\n    {\n        // this method is used only in restrictions, not in conditions where different rules apply for now\n        if (!isSupportedByRestrictionsOn(expression))\n            throw invalidRequest(\"%s cannot be used with %s relations\", this, expression);\n\n        switch (expression.kind())\n        {\n            case SINGLE_COLUMN:\n                ColumnMetadata firstColumn = expression.firstColumn();\n                AbstractType<?> columnType = firstColumn.type;\n                if (isSlice() && this != Operator.NEQ)\n                {\n                    if (columnType.referencesDuration())\n                    {\n                        checkFalse(columnType.isCollection(), \"Slice restrictions are not supported on collections containing durations\");\n                        checkFalse(columnType.isTuple(), \"Slice restrictions are not supported on tuples containing durations\");\n                        checkFalse(columnType.isUDT(), \"Slice restrictions are not supported on UDTs containing durations\");\n                        throw invalidRequest(\"Slice restrictions are not supported on duration columns\");\n                    }\n                }\n                else\n                {","sourceCodeStart":960,"sourceCodeEnd":996,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/Operator.java#L960-L996","documentation":"Cassandra validates that the comparison operator used in a relation (WHERE-clause restriction) is supported for the kind of columns expression it is applied to. `Operator.validateFor(ColumnsExpression)` calls `isSupportedByRestrictionsOn`; if the operator is not allowed for that restriction kind (e.g. multi-cell slice comparisons, token, CONTAINS, or LIKE applied where unsupported), it throws naming both the operator and the relation kind.","triggerScenarios":"CQL like `WHERE map_col > {..}` in a regular (non-indexed) restriction where slice operators are not permitted; using `CONTAINS`/`CONTAINS KEY` on a non-collection column; using `LIKE` on a non-text column; applying `IN` or slice operators to multi-column relations that don't support them.","commonSituations":"Querying a collection column with ordering operators without a suitable index (frozen + secondary index); expecting Map/List/Set ordering semantics in WHERE clauses; conditions written for conditions-column (JSON/UPDATE IF) syntax reused in SELECT restrictions where rules differ.","solutions":["Rewrite the relation using an operator supported for that column type (e.g. `=` or `IN` for collections, `CONTAINS`/`CONTAINS KEY` only for collections)","Create the required index (e.g. a collection index with `CREATE INDEX ... ON t(ENTRIES(col))`) if the operator requires one","Move the comparison into a client-side filter or into UPDATE ... IF conditions, where different operator rules apply","Change the column to a type that supports the operator (e.g. use a scalar text column with SASI/LIKE support for LIKE queries)"],"exampleFix":"// before\nSELECT * FROM t WHERE tags > {'a'};  -- slice on set not allowed in restrictions\n// after\nSELECT * FROM t WHERE tags CONTAINS 'a';","handlingStrategy":"validation","validationCode":"// Validate operator applicability before building the relation\nSet<Operator> collectionRestrictionOps = EnumSet.of(EQ, IN, CONTAINS, CONTAINS_KEY);\nif (isCollectionColumn(col) && !collectionRestrictionOps.contains(op))\n    throw new IllegalArgumentException(\"Operator \" + op + \" not allowed on collection restriction for \" + col);\nif (op == LIKE && !(col.getType().unwrap() instanceof TextType))\n    throw new IllegalArgumentException(\"LIKE requires a text column\");","typeGuard":null,"tryCatchPattern":"try {\n    return session.execute(query);\n} catch (InvalidRequestException e) {\n    if (e.getMessage().contains(\"cannot be used with\")) {\n        // fall back to an operator supported by restrictions on this column kind\n        return session.execute(rewriteWithSupportedOperator(query));\n    }\n    throw e;\n}","preventionTips":["Check operator rules per column kind: collections allow =, IN, CONTAINS, CONTAINS KEY (indexed); slices only on frozen collections with an index","Distinguish restriction (WHERE) rules from condition (UPDATE ... IF / JSON) rules — they differ","Create the matching index (KEYS/VALUES/ENTRIES/FULL) before using collection operators in restrictions","Test every generated WHERE clause against a real Cassandra instance in CI to surface prepare-time rejections"],"tags":["cql","operator","restriction","validation"],"backgroundTag":"unsupported-operation","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}