apache/cassandra · error · InvalidRequestException

Function ' ' is still referenced by aggregates

Error message

Function '%s' is still referenced by aggregates %s

What it means

Dependency guard in DropFunctionStatement.apply(): the user function being dropped is still referenced by one or more user-defined aggregates in the same keyspace. Dropping it would leave those aggregates with a missing target, so the statement is rejected with InvalidRequestException listing the dependent aggregate names (collected via aggregatesUsingFunction).

Solutions

  1. Drop the dependent aggregates first (DROP AGGREGATE), then retry the DROP FUNCTION; if the aggregates are no longer needed, drop them all as part of the same migration; keep the function if any aggregate still requires it.

Example fix

// before
DROP FUNCTION ks.avg_state (state);
// after
DROP AGGREGATE ks.avg (int);
DROP FUNCTION ks.avg_state (state);
Defensive patterns

Strategy: validation

Validate before calling

List<String> deps = keyspace.userFunctions.aggregatesUsingFunction(fn)
    .map(a -> a.name().toString()).collect(toList());
if (!deps.isEmpty()) dropAggregatesFirst(deps);

Try / catch

try { dropFunction(...); } catch (InvalidRequestException e) { if (e.getMessage().contains("still referenced by aggregates")) { /* parse names and DROP AGGREGATE first */ } else throw e; }

Prevention

When it happens

Trigger: DROP FUNCTION on a function referenced by CREATE AGGREGATE (as SFUNC, FINALFUNC, or state function) in the same keyspace; detected via keyspace.userFunctions.aggregatesUsingFunction(function).

Common situations: Forgetting which aggregates were built on top of a helper function during cleanup; dropping shared functions in a keyspace with many aggregates.

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

Appendix: source

Thrown at src/java/org/apache/cassandra/cql3/statements/schema/DropFunctionStatement.java:134

            filter = filter.and(f -> f.typesMatch(argumentTypes));

        UserFunction function = functions.stream().filter(filter).findAny().orElse(null);
        if (null == function)
        {
            if (ifExists)
                return schema;

            throw ire("Function '%s' doesn't exist", name);
        }

        String dependentAggregates =
            keyspace.userFunctions
                    .aggregatesUsingFunction(function)
                    .map(a -> a.name().toString())
                    .collect(joining(", "));

        if (!dependentAggregates.isEmpty())
            throw ire("Function '%s' is still referenced by aggregates %s", name, dependentAggregates);

        String dependentTables = keyspace.tablesUsingFunction(function)
                                         .map(table -> table.name)
                                         .collect(joining(", "));

        if (!dependentTables.isEmpty())
            throw ire("Function '%s' is still referenced by column masks in tables %s", name, dependentTables);

        return schema.withAddedOrUpdated(keyspace.withSwapped(keyspace.userFunctions.without(function)));
    }

    SchemaChange schemaChangeEvent(KeyspacesDiff diff)
    {
        UserFunctions dropped = diff.altered.get(0).udfs.dropped;
        assert dropped.size() == 1;
        return SchemaChange.forFunction(Change.DROPPED, (UDFunction) dropped.iterator().next());
    }

View on GitHub (pinned to 88fd0f6a0e)