apache/cassandra · error · InvalidRequestException

Final function isn't a scalar function

Error message

Final function %s isn't a scalar function

What it means

Thrown when the function named as FINALFUNC exists but is itself an aggregate (UDA) rather than a scalar function (UDF). A final function must be a plain scalar function transforming the state value; nesting aggregates is not allowed.

Solutions

  1. Point FINALFUNC at a scalar function created with CREATE FUNCTION, not an aggregate.
  2. Rename the colliding aggregate/function so the names are distinct.
  3. Drop the FINALFUNC clause if no final transformation is needed.

Example fix

// before
CREATE AGGREGATE ks.a(int) SFUNC s STYPE int FINALFUNC other_aggregate;
// after
CREATE AGGREGATE ks.a(int) SFUNC s STYPE int FINALFUNC scalar_final;
Defensive patterns

Strategy: validation

Validate before calling

var candidate = keyspace.userFunctions.find(finalFuncName, List.of(stateType));
if (candidate.isPresent() && candidate.get().isAggregate())
    throw new IllegalStateException(finalFuncName + " is an aggregate, not a scalar function");

Try / catch

try { session.execute(ddl); }
catch (InvalidRequestException e) {
    if (e.getMessage().contains("isn't a scalar function")) { /* use a UDF for FINALFUNC */ }
    else throw e;
}

Prevention

When it happens

Trigger: CREATE AGGREGATE ... FINALFUNC <name> where <name> resolves (with one argument of the state type) to an existing CREATE AGGREGATE definition instead of a CREATE FUNCTION definition.

Common situations: Name collision where an aggregate and function share a name; copy-pasting an aggregate name into the FINALFUNC slot by mistake.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/034a4041bbb9dc5b. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/cql3/statements/schema/CreateAggregateStatement.java:163

            throw ire("State function %s return type must be the same as the first argument type - check STYPE, argument and return types",
                      stateFunctionString());
        }

        /*
         * Resolve the final function and return type
         */

        UserFunction finalFunction = null;
        AbstractType<?> returnType = stateFunction.returnType();

        if (null != finalFunctionName)
        {
            finalFunction = keyspace.userFunctions.find(finalFunctionName, singletonList(stateType)).orElse(null);
            if (null == finalFunction)
                throw ire("Final function %s doesn't exist", finalFunctionString());

            if (finalFunction.isAggregate())
                throw ire("Final function %s isn't a scalar function", finalFunctionString());

            // override return type with that of the final function
            returnType = finalFunction.returnType();
        }

        /*
         * Validate initial condition
         */

        ByteBuffer initialValue = null;
        if (null != rawInitialValue)
        {
            String term = rawInitialValue.toString();
            initialValue = Term.asBytes(keyspaceName, term, stateType);

            if (null != initialValue)
            {
                try

View on GitHub (pinned to 88fd0f6a0e)