{"record":{"id":"ce447ea215b5b841","repo":"apache/cassandra","slug":"function-s-is-still-referenced-by-aggregates-s","errorCode":null,"errorMessage":"Function '%s' is still referenced by aggregates %s","messagePattern":"Function '(.+?)' is still referenced by aggregates (.+?)","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/statements/schema/DropFunctionStatement.java","lineNumber":134,"sourceCode":"            filter = filter.and(f -> f.typesMatch(argumentTypes));\n\n        UserFunction function = functions.stream().filter(filter).findAny().orElse(null);\n        if (null == function)\n        {\n            if (ifExists)\n                return schema;\n\n            throw ire(\"Function '%s' doesn't exist\", name);\n        }\n\n        String dependentAggregates =\n            keyspace.userFunctions\n                    .aggregatesUsingFunction(function)\n                    .map(a -> a.name().toString())\n                    .collect(joining(\", \"));\n\n        if (!dependentAggregates.isEmpty())\n            throw ire(\"Function '%s' is still referenced by aggregates %s\", name, dependentAggregates);\n\n        String dependentTables = keyspace.tablesUsingFunction(function)\n                                         .map(table -> table.name)\n                                         .collect(joining(\", \"));\n\n        if (!dependentTables.isEmpty())\n            throw ire(\"Function '%s' is still referenced by column masks in tables %s\", name, dependentTables);\n\n        return schema.withAddedOrUpdated(keyspace.withSwapped(keyspace.userFunctions.without(function)));\n    }\n\n    SchemaChange schemaChangeEvent(KeyspacesDiff diff)\n    {\n        UserFunctions dropped = diff.altered.get(0).udfs.dropped;\n        assert dropped.size() == 1;\n        return SchemaChange.forFunction(Change.DROPPED, (UDFunction) dropped.iterator().next());\n    }\n","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/statements/schema/DropFunctionStatement.java#L116-L152","documentation":"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).","triggerScenarios":"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).","commonSituations":"Forgetting which aggregates were built on top of a helper function during cleanup; dropping shared functions in a keyspace with many aggregates.","solutions":["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."],"exampleFix":"// before\nDROP FUNCTION ks.avg_state (state);\n// after\nDROP AGGREGATE ks.avg (int);\nDROP FUNCTION ks.avg_state (state);","handlingStrategy":"validation","validationCode":"List<String> deps = keyspace.userFunctions.aggregatesUsingFunction(fn)\n    .map(a -> a.name().toString()).collect(toList());\nif (!deps.isEmpty()) dropAggregatesFirst(deps);","typeGuard":null,"tryCatchPattern":"try { dropFunction(...); } catch (InvalidRequestException e) { if (e.getMessage().contains(\"still referenced by aggregates\")) { /* parse names and DROP AGGREGATE first */ } else throw e; }","preventionTips":["Track aggregate-to-function dependencies in schema docs","Drop aggregates before their state/final functions","Use naming conventions making dependents discoverable"],"tags":["cql","schema","udf","uda"],"backgroundTag":"unsupported-operation","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}