apache/cassandra · error · InvalidRequestException

Cannot use both 'OR REPLACE' and 'IF NOT EXISTS' directives

Error message

Cannot use both 'OR REPLACE' and 'IF NOT EXISTS' directives

What it means

Thrown by CreateFunctionStatement.apply (also exercised via CREATE AGGREGATE's shared parsing path) when a statement specifies both OR REPLACE and IF NOT EXISTS. The two directives are mutually exclusive: one forces overwrite, the other forbids overwrite.

Solutions

  1. Remove IF NOT EXISTS if the intent is to overwrite.
  2. Remove OR REPLACE if the intent is create-if-absent.
  3. Make the DDL generator emit exactly one of the two flags.

Example fix

// before
CREATE FUNCTION OR REPLACE IF NOT EXISTS ks.f(i int) ...;
// after
CREATE FUNCTION OR REPLACE ks.f(i int) ...;
Defensive patterns

Strategy: validation

Validate before calling

if (orReplace && ifNotExists)
    throw new IllegalArgumentException("Use either OR REPLACE or IF NOT EXISTS, not both");

Try / catch

try { session.execute(ddl); }
catch (InvalidRequestException e) {
    if (e.getMessage().contains("both 'OR REPLACE' and 'IF NOT EXISTS'")) { /* strip one flag and retry */ }
    else throw e;
}

Prevention

When it happens

Trigger: CREATE FUNCTION (or CREATE AGGREGATE) ... OR REPLACE ... IF NOT EXISTS ... in the same statement.

Common situations: Script generators appending both flags defensively; hand-merged DDL from two templates; macro/ORM code adding IF NOT EXISTS to an existing OR REPLACE statement.

Understand the failure class

Background: "mutually exclusive" flag errors: what "can't supply both nx and xx", "--raw is not compatible with -i" and "cannot be used with" mean, and how to fix them — this error's family across 29 libraries.

Related errors


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

Appendix: source

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

        this.rawReturnType = rawReturnType;
        this.calledOnNullInput = calledOnNullInput;
        this.language = language;
        this.body = body;
        this.orReplace = orReplace;
        this.ifNotExists = ifNotExists;
    }

    @Override
    public boolean compatibleWith(ClusterMetadata metadata)
    {
        return metadata.directory.commonSerializationVersion.isAtLeast(Version.V0);
    }

    // TODO: replace affected aggregates !!
    public Keyspaces apply(ClusterMetadata metadata)
    {
        if (ifNotExists && orReplace)
            throw ire("Cannot use both 'OR REPLACE' and 'IF NOT EXISTS' directives");

        UDFunction.assertUdfsEnabled(language);

        if (!FunctionName.isNameValid(functionName))
            throw ire("Function name '%s' is invalid", functionName);

        if (new HashSet<>(argumentNames).size() != argumentNames.size())
            throw ire("Duplicate argument names for given function %s with argument names %s", functionName, argumentNames);

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

        if (!rawReturnType.isImplicitlyFrozen() && rawReturnType.isFrozen())
            throw ire("Return type '%s' cannot be frozen; remove frozen<> modifier from '%s'", rawReturnType, rawReturnType);

        Keyspaces schema = metadata.schema.getKeyspaces();

View on GitHub (pinned to 88fd0f6a0e)