apache/cassandra · error · InvalidRequestException

Multicolumn IN filters are not supported

Error message

Multicolumn IN filters are not supported

What it means

Row filtering does not support IN predicates over multiple columns. When an IN restriction is processed in addToRowFilter and it spans more than one column, Cassandra throws because multi-column IN cannot be expressed as a row filter.

Solutions

  1. Rewrite as separate single-column equality restrictions, or multiple queries per tuple
  2. Create an index that lets the multicolumn predicate be resolved without row filtering
  3. Expand the tuple IN into multiple queries, one per tuple, in application code

Example fix

// before
SELECT * FROM t WHERE (a, b) IN ((1,2),(3,4));
// after
SELECT * FROM t WHERE a = 1 AND b = 2;
SELECT * FROM t WHERE a = 3 AND b = 4;
Defensive patterns

Strategy: fallback

Validate before calling

if (inPredicate.columns().size() > 1) useExpandedQueriesOrAllowFiltering();

Try / catch

catch (InvalidRequestException e) { if (e.getMessage().contains("Multicolumn IN")) expandIntoSingleColumnQueries(); }

Prevention

When it happens

Trigger: A query requiring filtering (ALLOW FILTERING or no index) where the predicate is a multicolumn IN, e.g. 'WHERE (a, b) IN ((1,2),(3,4))' with no usable index.

Common situations: Tuple IN queries on non-key columns without an index; generated queries that assume multicolumn IN is always executable.

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/700ad098cf952f7e. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/cql3/restrictions/SimpleRestriction.java:431

                        ColumnMetadata columnDef = columns().get(i);
                        filter.add(columnDef, Operator.EQ, elements.get(i));
                    }
                }
                else if (isIN())
                {
                    // If the relation is of the type (c) IN ((x),(y),(z)) then it is equivalent to
                    // c IN (x, y, z) and we can perform filtering
                    if (columns().size() == 1)
                    {
                        List<ByteBuffer> values = bindAndGetElements(context).stream()
                                                                             .map(elements -> elements.get(0))
                                                                             .collect(Collectors.toList());

                        filter.add(firstColumn(), Operator.IN, multiInputOperatorValues(firstColumn(), values));
                    }
                    else
                    {
                        throw invalidRequest("Multicolumn IN filters are not supported");
                    }
                }
                break;
            case ELEMENT:
                // TODO only map elements supported for now
                if (columnsExpression.isMapElementExpression())
                {
                    // For frozen maps, check if any index on the column can support map entry predicates
                    // either directly or via filtering. If not, throw an error.
                    if (column.type.isFrozenCollection())
                    {
                        for (Index index : indexRegistry.listIndexes())
                        {
                            if (index.dependsOn(column)
                                && !index.supportsMapElementExpression()
                                && !index.supportsFilteringOnMapElementExpression())
                            {
                                throw invalidRequest(Relation.FROZEN_MAP_ENTRY_PREDICATES_NOT_SUPPORTED, column.name);

View on GitHub (pinned to 88fd0f6a0e)