apache/cassandra · error · InvalidRequestException

Aggregate function cannot be used for masking table columns

Error message

Aggregate function %s cannot be used for masking table columns

What it means

ColumnMask.findMaskingFunction rejects aggregate functions used in a MASKED WITH clause. Masking requires a ScalarFunction that transforms a single column value; aggregates consume many rows and cannot be applied per-value. The check is function.isAggregate() after resolution.

Solutions

  1. Replace the aggregate with a dedicated masking function such as mask_null, mask_default, mask_inner, mask_outer, or hash.
  2. If custom masking is needed, write a scalar UDF in the same keyspace that returns the same type as the column.

Example fix

// before
ALTER TABLE users ALTER age MASKED WITH sum(age);
// after
ALTER TABLE users ALTER age MASKED WITH mask_default(int);
Defensive patterns

Strategy: validation

Validate before calling

Set<String> aggregates = Set.of("count","sum","avg","max","min");
if (aggregates.contains(fnName.toLowerCase())) throw new IllegalArgumentException("aggregates cannot mask columns");

Prevention

When it happens

Trigger: MASKED WITH sum(int) or any other aggregate (count, avg, max, ...) attached to a column in CREATE TABLE / ALTER TABLE masked-column DDL.

Common situations: Developer assumes any CQL function can mask a column and picks an aggregate like sum() or count() instead of the intended masking built-ins.

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

Appendix: source

Thrown at src/java/org/apache/cassandra/cql3/functions/masking/ColumnMask.java:250

            ByteBuffer[] partialArguments = preparePartialArguments(keyspace, function);
            return new ColumnMask(function, partialArguments);
        }

        private ScalarFunction findMaskingFunction(String keyspace, String table, ColumnIdentifier column, AbstractType<?> type, UserFunctions functions)
        {
            List<AssignmentTestable> args = new ArrayList<>(rawPartialArguments.size() + 1);
            args.add(type);
            args.addAll(rawPartialArguments);

            Function function = FunctionResolver.get(keyspace, name, args, keyspace, table, type, functions);

            if (function == null)
                throw invalidRequest("Unable to find masking function for %s, " +
                                     "no declared function matches the signature %s",
                                     column, this);

            if (function.isAggregate())
                throw invalidRequest("Aggregate function %s cannot be used for masking table columns", this);

            if (function.isNative() && !(function instanceof MaskingFunction))
                throw invalidRequest("Not-masking function %s cannot be used for masking table columns", this);

            if (!function.isNative() && !function.name().keyspace.equals(keyspace))
                throw invalidRequest("Masking function %s doesn't belong to the same keyspace as the table %s.%s",
                                     this, keyspace, table);

            CQL3Type returnType = function.returnType().asCQL3Type();
            CQL3Type expectedType = type.asCQL3Type();
            if (!returnType.equals(expectedType))
                throw invalidRequest("Masking function %s return type is %s. " +
                                     "This is different to the type of the masked column %s of type %s. " +
                                     "Masking functions can only be attached to table columns " +
                                     "if they return the same data type as the masked column.",
                                     this, returnType, column, expectedType);

            return (ScalarFunction) function;

View on GitHub (pinned to 88fd0f6a0e)