apache/cassandra · error · InvalidRequestException

'DROP FUNCTION ' matches multiple function definitions…

Error message

'DROP FUNCTION %s' matches multiple function definitions; specify the argument types by issuing a statement like 'DROP FUNCTION %s (type, type, ...)'. You can use cqlsh 'DESCRIBE FUNCTION %s' command to find all overloads

What it means

Multiple overloads of the named function exist in the keyspace and the DROP FUNCTION statement omitted the argument type list, making the target ambiguous. Cassandra requires explicit argument types to disambiguate.

Solutions

  1. Specify argument types: DROP FUNCTION ks.fn (type1, type2);
  2. List overloads via cqlsh 'DESCRIBE FUNCTION ks.fn' or system_schema.functions
  3. Keep overload sets minimal to avoid recurring ambiguity

Example fix

// before
DROP FUNCTION sales.my_func;
// after
DROP FUNCTION sales.my_func (int, text);
Defensive patterns

Strategy: validation

Validate before calling

const rows = await session.execute("SELECT argument_types, count(*) FROM system_schema.functions WHERE keyspace_name=? AND function_name=? GROUP BY argument_types", [ks, name]); if (rows.rowLength > 1) throw new Error('Ambiguous: specify argument types');

Try / catch

try { session.execute(ddl); } catch (e) { if (e instanceof InvalidQueryError && /matches multiple function definitions/.test(e.message)) { /* re-issue with explicit (type, ...) list */ } else throw e; }

Prevention

When it happens

Trigger: DROP FUNCTION fn (no type list) when two or more UDFs named fn with different signatures exist in the keyspace.

Common situations: Overloaded UDFs with same name/different types; shared migration scripts dropping by name; not using DESCRIBE FUNCTION to inspect overloads.

Related errors


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

Appendix: source

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

        String name =
            argumentsSpeficied
          ? format("%s.%s(%s)", keyspaceName, functionName, join(", ", transform(arguments, CQL3Type.Raw::toString)))
          : format("%s.%s", keyspaceName, functionName);

        Keyspaces schema = metadata.schema.getKeyspaces();
        KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
        if (null == keyspace)
        {
            if (ifExists)
                return schema;

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

        Collection<UserFunction> functions = keyspace.userFunctions.get(new FunctionName(keyspaceName, functionName));
        if (functions.size() > 1 && !argumentsSpeficied)
        {
            throw ire("'DROP FUNCTION %s' matches multiple function definitions; " +
                      "specify the argument types by issuing a statement like " +
                      "'DROP FUNCTION %s (type, type, ...)'. You can use cqlsh " +
                      "'DESCRIBE FUNCTION %s' command to find all overloads",
                      functionName, functionName, functionName);
        }

        arguments.stream()
                 .filter(raw -> !raw.isImplicitlyFrozen() && raw.isFrozen())
                 .findFirst()
                 .ifPresent(t -> { throw ire("Argument '%s' cannot be frozen; remove frozen<> modifier from '%s'", t, t); });

        List<AbstractType<?>> argumentTypes = prepareArgumentTypes(keyspace.types);

        Predicate<UserFunction> filter = UserFunctions.Filter.UDF;
        if (argumentsSpeficied)
            filter = filter.and(f -> f.typesMatch(argumentTypes));

        UserFunction function = functions.stream().filter(filter).findAny().orElse(null);

View on GitHub (pinned to 88fd0f6a0e)