apache/cassandra · error · InvalidRequestException
Custom index expressions cannot be used in WHERE clauses for
Error message
Custom index expressions cannot be used in WHERE clauses for UPDATE or DELETE statements
What it means
In ModificationStatement's restrictions builder, if the WHERE clause of an UPDATE or DELETE contains custom index expressions (e.g. expr(idx, ...)), this InvalidRequestException is thrown. Custom index expressions are only permitted in SELECT statements, never in data-modifying statements.
Source
Thrown at src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java:1428
* Creates the restrictions.
*
* @param metadata the table meta data
* @param boundNames the bound names
* @param operations the column operations
* @param where the where clause
* @param conditions the conditions
* @return the restrictions
*/
protected StatementRestrictions newRestrictions(ClientState state,
TableMetadata metadata,
VariableSpecifications boundNames,
Operations operations,
WhereClause where,
Conditions conditions,
Object owner)
{
if (where.containsCustomExpressions())
throw new InvalidRequestException(CUSTOM_EXPRESSIONS_NOT_ALLOWED);
boolean applyOnlyToStaticColumns = appliesOnlyToStaticColumns(operations, conditions);
return new StatementRestrictions(state, type, metadata, IndexHints.NONE, where, boundNames, Collections.emptyList(), owner, applyOnlyToStaticColumns, false, false);
}
public List<ColumnCondition.Raw> getConditions()
{
return conditions;
}
}
private static final Constants.Value ONE = new Constants.Value(ByteBufferUtil.bytes(1));
public SelectStatement createSelectForTxn()
{
// TODO: get working with static-only updates that don't specify any/all primary key columns
Preconditions.checkState(getRestrictions().hasAllPrimaryKeyColumnsRestrictedByEqualities());
Selection selection = Selection.forColumns(metadata, Lists.newArrayList(requiresRead), false);View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Remove the custom index expression and identify target rows via primary-key columns instead.
- Rewrite as a SELECT to find the keys first, then issue an UPDATE/DELETE on those keys.
- Reconsider the data model so the target rows are addressable by their primary key.
Example fix
// before DELETE FROM t WHERE expr(custom_idx, tags) = 'x'; // after SELECT pk FROM t WHERE expr(custom_idx, tags) = 'x'; DELETE FROM t WHERE pk = <found key>;
Defensive patterns
Strategy: validation
Validate before calling
if (statementType != SELECT && whereClause.containsCustomIndexExpression()) throw new IllegalArgumentException("custom index expressions only allowed in SELECT"); Prevention
- Never reuse SELECT WHERE clauses verbatim for UPDATE/DELETE
- Address target rows by primary key in mutations
- Audit ORM/query builders for expr() emission in mutations
When it happens
Trigger: UPDATE ... WHERE expr(my_index, col) = ... or DELETE with a custom-index expression in the WHERE clause.
Common situations: Copying a SELECT's WHERE clause into an UPDATE/DELETE; ORM/query builders emitting index expressions generically.
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
- WHERE clause for materialized view '%s' cannot contain custo
- IndexRestrictions.MULTIPLE_EXPRESSIONS
- Aggregation function are not supported in the where clause
- Non PRIMARY KEY columns found in where clause: %s
- Clustering key columns must exactly match columns in CLUSTER
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/781d75f938ac91fe.
Report an issue: GitHub.