apache/cassandra · error · InvalidRequestException

IndexRestrictions.MULTIPLE_EXPRESSIONS

Error message

IndexRestrictions.MULTIPLE_EXPRESSIONS

What it means

Custom index expressions (the legacy 'expr(idx, ...)' syntax) may only be used with indexes that support multiple expressions; otherwise at most one expression per statement is allowed. processCustomIndexExpressions throws IndexRestrictions.MULTIPLE_EXPRESSIONS when more than one expression is given and the target index backend does not declare support.

Source

Thrown at src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java:741

        missingClusteringColumns.removeAll(new LinkedList<>(clusteringColumnsRestrictions.columns()));
        return ColumnMetadata.toIdentifiers(missingClusteringColumns);
    }

    /**
     * Checks if some clustering columns are not restricted.
     * @return <code>true</code> if some clustering columns are not restricted, <code>false</code> otherwise.
     */
    private boolean hasUnrestrictedClusteringColumns()
    {
        return table.clusteringColumns().size() != clusteringColumnsRestrictions.size();
    }

    private void processCustomIndexExpressions(List<CustomIndexExpression> expressions,
                                               VariableSpecifications boundNames,
                                               IndexRegistry indexRegistry)
    {
        if (expressions.size() > 1 && !indexRegistry.supportsMultipleIndexExpressions())
            throw new InvalidRequestException(IndexRestrictions.MULTIPLE_EXPRESSIONS);

        for (CustomIndexExpression expression : expressions)
        {
            QualifiedName name = expression.targetIndex;

            if (name.hasKeyspace() && !name.getKeyspace().equals(table.keyspace))
                throw IndexRestrictions.invalidIndex(expression.targetIndex, table);

            if (!table.indexes.has(expression.targetIndex.getName()))
                throw IndexRestrictions.indexNotFound(expression.targetIndex, table);

            Index index = indexRegistry.getIndex(table.indexes.get(expression.targetIndex.getName()).get());
            if (!index.getIndexMetadata().isCustom())
                throw IndexRestrictions.nonCustomIndexInExpression(expression.targetIndex);

            AbstractType<?> expressionType = index.customExpressionValueType();
            if (expressionType == null)
                throw IndexRestrictions.customExpressionNotSupported(expression.targetIndex);

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Combine the conditions into a single expression string if the index supports it (e.g. one expr with a compound query).
  2. Remove the extra expressions and filter remaining conditions client-side or with normal WHERE clauses.
  3. Switch to an index implementation that supports multiple index expressions.

Example fix

// before
SELECT * FROM t WHERE expr(idx, 'age > 30'), expr(idx, 'city = Paris');
// after
SELECT * FROM t WHERE expr(idx, 'age > 30 AND city = Paris');
Defensive patterns

Strategy: validation

Validate before calling

if (customExpressions.size() > 1 && !indexSupportsMultipleExpressions)
    throw new IllegalArgumentException("target index supports only a single custom expression");

Try / catch

try { session.execute(stmt); }
catch (InvalidRequestException e) {
    if (e.getMessage().contains("multiple expressions")) { /* merge conditions into one expr */ }
    else throw e;
}

Prevention

When it happens

Trigger: A SELECT with two or more CustomIndexExpression terms (e.g. expr(myidx, 'a'), expr(myidx, 'b')) against a custom index implementation whose supportsMultipleIndexExpressions() returns false (e.g. plain StorageAttachedIndex vs. legacy index backends).

Common situations: Using Lucene/other third-party index syntax patterns that accept multiple conditions, against an index implementation that only handles a single expression.

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


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/c5afaa9abe743df2. Report an issue: GitHub.