apache/cassandra · error · InvalidRequestException
%s cannot be used with %s relations
Error message
%s cannot be used with %s relations
What it means
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.
Source
Thrown at src/java/org/apache/cassandra/cql3/Operator.java:978
List<ByteBuffer> unpackMultiCellElements(MultiElementType<?> type, ByteBuffer value)
{
checkTrue(value != null, "Invalid comparison with null for operator \"%s\"", this);
List<ByteBuffer> elements = type.unpack(value);
if (type.isCollection() && elements.isEmpty())
throw invalidRequest("Invalid comparison with an empty %s for operator \"%s\"", ((CollectionType<?>) type).kind, this);
return elements;
}
public static int serializedSize()
{
return 4;
}
public void validateFor(ColumnsExpression expression)
{
// this method is used only in restrictions, not in conditions where different rules apply for now
if (!isSupportedByRestrictionsOn(expression))
throw invalidRequest("%s cannot be used with %s relations", this, expression);
switch (expression.kind())
{
case SINGLE_COLUMN:
ColumnMetadata firstColumn = expression.firstColumn();
AbstractType<?> columnType = firstColumn.type;
if (isSlice() && this != Operator.NEQ)
{
if (columnType.referencesDuration())
{
checkFalse(columnType.isCollection(), "Slice restrictions are not supported on collections containing durations");
checkFalse(columnType.isTuple(), "Slice restrictions are not supported on tuples containing durations");
checkFalse(columnType.isUDT(), "Slice restrictions are not supported on UDTs containing durations");
throw invalidRequest("Slice restrictions are not supported on duration columns");
}
}
else
{View on GitHub (pinned to 88fd0f6a0e)
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)
Example fix
// before
SELECT * FROM t WHERE tags > {'a'}; -- slice on set not allowed in restrictions
// after
SELECT * FROM t WHERE tags CONTAINS 'a'; Defensive patterns
Strategy: validation
Validate before calling
// Validate operator applicability before building the relation
Set<Operator> collectionRestrictionOps = EnumSet.of(EQ, IN, CONTAINS, CONTAINS_KEY);
if (isCollectionColumn(col) && !collectionRestrictionOps.contains(op))
throw new IllegalArgumentException("Operator " + op + " not allowed on collection restriction for " + col);
if (op == LIKE && !(col.getType().unwrap() instanceof TextType))
throw new IllegalArgumentException("LIKE requires a text column"); Try / catch
try {
return session.execute(query);
} catch (InvalidRequestException e) {
if (e.getMessage().contains("cannot be used with")) {
// fall back to an operator supported by restrictions on this column kind
return session.execute(rewriteWithSupportedOperator(query));
}
throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- REVOKE operation is not supported by AllowAllAuthorizer
- Invalid operation (%s) for non-numeric and non-text type %s
- Key may not be empty
- Key may not be empty
- Key length of %d is longer than maximum of %d
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/9d239fc96ce65325.
Report an issue: GitHub.