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

Syntax-validation guard in CREATE AGGREGATE: the CQL grammar permits both 'OR REPLACE' and 'IF NOT EXISTS', but they are mutually exclusive directives, so applying the schema transformation rejects statements that specify both.

Solutions

  1. Remove either OR REPLACE or IF NOT EXISTS from the CREATE AGGREGATE statement
  2. Use OR REPLACE to unconditionally replace an existing aggregate
  3. Use IF NOT EXISTS to skip creation when it already exists

Example fix

// before
CREATE AGGREGATE IF NOT EXISTS OR REPLACE ks.avg(int);
// after
CREATE AGGREGATE OR REPLACE ks.avg(int);
Defensive patterns

Strategy: validation

Validate before calling

if (ddl.matches("(?s)IF\\s+NOT\\s+EXISTS") && ddl.matches("(?s)OR\\s+REPLACE"))
    throw new IllegalArgumentException("Use either IF NOT EXISTS or OR REPLACE, not both");

Try / catch

try { session.execute(ddl); }
catch (InvalidRequestException e) { if (e.getMessage().contains("both 'OR REPLACE' and 'IF NOT EXISTS'")) stripFlagsAndRetry(ddl); else throw e; }

Prevention

When it happens

Trigger: Executing CREATE AGGREGATE [IF NOT EXISTS] ... [OR REPLACE] ... with both flags parsed true; checked first in CreateAggregateStatement.apply.

Common situations: Copy-pasting template DDL that combined both idempotence clauses; merging two scripts each adding one directive.

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/cd1646be28280b6d. Report an issue: GitHub.

Appendix: source

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

        this.rawStateType = rawStateType;
        this.stateFunctionName = stateFunctionName;
        this.finalFunctionName = finalFunctionName;
        this.rawInitialValue = rawInitialValue;
        this.orReplace = orReplace;
        this.ifNotExists = ifNotExists;
    }

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

    @Override
    public Keyspaces apply(ClusterMetadata metadata)
    {
        if (ifNotExists && orReplace)
            throw ire("Cannot use both 'OR REPLACE' and 'IF NOT EXISTS' directives");

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

        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 (!rawStateType.isImplicitlyFrozen() && rawStateType.isFrozen())
            throw ire("State type '%s' cannot be frozen; remove frozen<> modifier from '%s'", rawStateType, rawStateType);

        Keyspaces schema = metadata.schema.getKeyspaces();
        KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
        if (null == keyspace)
            throw ire("Keyspace '%s' doesn't exist", keyspaceName);

        /*

View on GitHub (pinned to 88fd0f6a0e)