apache/cassandra · error · InvalidRequestException

Function ' ' already exists

Error message

Function '%s' already exists

What it means

A CREATE FUNCTION statement attempted to create a function that already exists (same name and argument types) without IF NOT EXISTS or OR REPLACE. The statement returns early for ifNotExists, but otherwise throws this InvalidRequestException when orReplace is false.

Solutions

  1. Add OR REPLACE to update the existing function
  2. Add IF NOT EXISTS to make the statement a no-op when the function exists
  3. Drop the function first with DROP FUNCTION if a clean recreate is intended

Example fix

// before
CREATE FUNCTION ks.f(int) RETURNS NULL ON NULL INPUT RETURNS int ...
// after
CREATE OR REPLACE FUNCTION ks.f(int) RETURNS NULL ON NULL INPUT RETURNS int ...
Defensive patterns

Strategy: validation

Validate before calling

ResultSet rs = session.execute("SELECT argument_types FROM system_schema.functions WHERE keyspace_name = ? AND function_name = ?", ks, fn);
if (!rs.all().isEmpty() && !stmtUsesOrReplace) throw new IllegalStateException("Function already exists: " + fn);

Try / catch

try { session.execute(stmt); } catch (InvalidRequestException e) { if (e.getMessage().endsWith("already exists")) { /* add OR REPLACE/IF NOT EXISTS or skip */ } else throw e; }

Prevention

When it happens

Trigger: Re-running CREATE FUNCTION for an existing signature without OR REPLACE/IF NOT EXISTS; idempotent migration scripts that omit OR REPLACE.

Common situations: Replaying DDL migration scripts; concurrent deployments both creating the same function; recreating a function after a partial rollback.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/cql3/statements/schema/CreateFunctionStatement.java:146

            UDFunction.create(new FunctionName(keyspaceName, functionName),
                              argumentNames,
                              argumentTypes,
                              returnType,
                              calledOnNullInput,
                              language,
                              body);

        UserFunction existingFunction = keyspace.userFunctions.find(function.name(), argumentTypes).orElse(null);
        if (null != existingFunction)
        {
            if (existingFunction.isAggregate())
                throw ire("Function '%s' cannot replace an aggregate", functionName);

            if (ifNotExists)
                return schema;

            if (!orReplace)
                throw ire("Function '%s' already exists", functionName);

            if (calledOnNullInput != ((UDFunction) existingFunction).isCalledOnNullInput())
            {
                throw ire("Function '%s' must have %s directive",
                          functionName,
                          calledOnNullInput ? "CALLED ON NULL INPUT" : "RETURNS NULL ON NULL INPUT");
            }

            if (!returnType.isCompatibleWith(existingFunction.returnType()))
            {
                throw ire("Cannot replace function '%s', the new return type %s is not compatible with the return type %s of existing function",
                          functionName,
                          returnType.asCQL3Type(),
                          existingFunction.returnType().asCQL3Type());
            }

            // TODO: update dependent aggregates
        }

View on GitHub (pinned to 88fd0f6a0e)