{"record":{"id":"adb5a3bab58ea2d4","repo":"apache/cassandra","slug":"cannot-replace-aggregate-s-the-new-return-type","errorCode":null,"errorMessage":"Cannot replace aggregate '%s', the new return type %s isn't compatible with the return type %s of existing function","messagePattern":"Cannot replace aggregate '(.+?)', the new return type (.+?) isn't compatible with the return type (.+?) of existing function","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/statements/schema/CreateAggregateStatement.java","lineNumber":233,"sourceCode":"                            (ScalarFunction) stateFunction,\n                            (ScalarFunction) finalFunction,\n                            initialValue);\n\n        UserFunction existingAggregate = keyspace.userFunctions.find(aggregate.name(), argumentTypes).orElse(null);\n        if (null != existingAggregate)\n        {\n            if (!existingAggregate.isAggregate())\n                throw ire(\"Aggregate '%s' cannot replace a function\", aggregateName);\n\n            if (ifNotExists)\n                return schema;\n\n            if (!orReplace)\n                throw ire(\"Aggregate '%s' already exists\", aggregateName);\n\n            if (!returnType.isCompatibleWith(existingAggregate.returnType()))\n            {\n                throw ire(\"Cannot replace aggregate '%s', the new return type %s isn't compatible with the return type %s of existing function\",\n                          aggregateName,\n                          returnType.asCQL3Type(),\n                          existingAggregate.returnType().asCQL3Type());\n            }\n        }\n\n        return schema.withAddedOrUpdated(keyspace.withSwapped(keyspace.userFunctions.withAddedOrUpdated(aggregate)));\n    }\n\n    private static boolean isNullOrEmpty(AbstractType<?> type, ByteBuffer bb)\n    {\n        return bb == null ||\n               (bb.remaining() == 0 && type.isEmptyValueMeaningless());\n    }\n\n    SchemaChange schemaChangeEvent(KeyspacesDiff diff)\n    {\n        assert diff.altered.size() == 1;","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/statements/schema/CreateAggregateStatement.java#L215-L251","documentation":"Thrown when OR REPLACE is used to replace an existing aggregate but the new aggregate's return type is not compatible with the existing one's return type. Cassandra prevents replacing an aggregate in a way that changes its output type incompatibly.","triggerScenarios":"CREATE AGGREGATE OR REPLACE where the final function (or state function) yields a return type that fails AbstractType.isCompatibleWith against the existing aggregate's return type — e.g. replacing a double-returning aggregate with an int-returning one.","commonSituations":"Changing FINALFUNC to one with a different return type while reusing OR REPLACE; widening/narrowing state type during schema evolution.","solutions":["Keep the new return type compatible with the existing one (choose a final function whose return type is compatible).","DROP AGGREGATE the old aggregate, then CREATE the new one with the desired return type.","Update all dependent queries/views that rely on the old return type before replacing."],"exampleFix":"// before\nCREATE AGGREGATE OR REPLACE ks.avg(int) SFUNC s STYPE int FINALFUNC to_int; -- was double-returning\n// after\nDROP AGGREGATE ks.avg(int);\nCREATE AGGREGATE ks.avg(int) SFUNC s STYPE int FINALFUNC to_int;","handlingStrategy":"validation","validationCode":"var existing = keyspace.userFunctions.find(fnName, argTypes);\nif (existing.isPresent() && existing.get().isAggregate() && useOrReplace\n    && !newReturnType.isCompatibleWith(existing.get().returnType()))\n    throw new IllegalStateException(\"Return type \" + newReturnType + \" incompatible with existing \" + existing.get().returnType());","typeGuard":null,"tryCatchPattern":"try { session.execute(ddl); }\ncatch (InvalidRequestException e) {\n    if (e.getMessage().contains(\"isn't compatible\")) { /* DROP AGGREGATE then recreate */ }\n    else throw e;\n}","preventionTips":["Keep FINALFUNC return type stable across replacements.","Drop-and-recreate when the return type must change.","Document return-type expectations next to aggregate DDL."],"tags":["cql","type-mismatch","schema-evolution"],"backgroundTag":"type-mismatch","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"}