apache/cassandra · error · InvalidRequestException
Cannot replace aggregate
Error message
Cannot replace aggregate '%s', the new return type %s isn't compatible with the return type %s of existing function
What it means
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.
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.
Example fix
// before CREATE AGGREGATE OR REPLACE ks.avg(int) SFUNC s STYPE int FINALFUNC to_int; -- was double-returning // after DROP AGGREGATE ks.avg(int); CREATE AGGREGATE ks.avg(int) SFUNC s STYPE int FINALFUNC to_int;
Defensive patterns
Strategy: validation
Validate before calling
var existing = keyspace.userFunctions.find(fnName, argTypes);
if (existing.isPresent() && existing.get().isAggregate() && useOrReplace
&& !newReturnType.isCompatibleWith(existing.get().returnType()))
throw new IllegalStateException("Return type " + newReturnType + " incompatible with existing " + existing.get().returnType()); Try / catch
try { session.execute(ddl); }
catch (InvalidRequestException e) {
if (e.getMessage().contains("isn't compatible")) { /* DROP AGGREGATE then recreate */ }
else throw e;
} Prevention
- Keep FINALFUNC return type stable across replacements.
- Drop-and-recreate when the return type must change.
- Document return-type expectations next to aggregate DDL.
When it happens
Trigger: 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.
Common situations: Changing FINALFUNC to one with a different return type while reusing OR REPLACE; widening/narrowing state type during schema evolution.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Cannot assign value to of type
- Cannot assign value to of type
- Cannot cast value to type
- Cannot replace function
- Constraint ' ' can be used only for columns of type but it…
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/adb5a3bab58ea2d4.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/cql3/statements/schema/CreateAggregateStatement.java:233
(ScalarFunction) stateFunction,
(ScalarFunction) finalFunction,
initialValue);
UserFunction existingAggregate = keyspace.userFunctions.find(aggregate.name(), argumentTypes).orElse(null);
if (null != existingAggregate)
{
if (!existingAggregate.isAggregate())
throw ire("Aggregate '%s' cannot replace a function", aggregateName);
if (ifNotExists)
return schema;
if (!orReplace)
throw ire("Aggregate '%s' already exists", aggregateName);
if (!returnType.isCompatibleWith(existingAggregate.returnType()))
{
throw ire("Cannot replace aggregate '%s', the new return type %s isn't compatible with the return type %s of existing function",
aggregateName,
returnType.asCQL3Type(),
existingAggregate.returnType().asCQL3Type());
}
}
return schema.withAddedOrUpdated(keyspace.withSwapped(keyspace.userFunctions.withAddedOrUpdated(aggregate)));
}
private static boolean isNullOrEmpty(AbstractType<?> type, ByteBuffer bb)
{
return bb == null ||
(bb.remaining() == 0 && type.isEmptyValueMeaningless());
}
SchemaChange schemaChangeEvent(KeyspacesDiff diff)
{
assert diff.altered.size() == 1;View on GitHub (pinned to 88fd0f6a0e)