apache/cassandra · error · InvalidRequestException

Cannot mix IF conditions and %s for the same row

Error message

Cannot mix IF conditions and %s for the same row

What it means

Cassandra's lightweight-transaction (CAS) layer requires that all conditions for a given row be of the same kind. CQL3CasRequest.addConditions throws InvalidRequestException when a second batch of conditions is added for a row whose existing condition is not a ColumnsConditions (i.e., the row already has an EXISTS/NOT_EXISTS condition or a different condition type), because mixing IF column conditions and row-existence checks on the same row cannot be evaluated as one atomic predicate.

Source

Thrown at src/java/org/apache/cassandra/cql3/statements/CQL3CasRequest.java:209

                    : new InvalidRequestException("Cannot mix IF conditions and IF " + (isNotExist ? "NOT " : "") + "EXISTS for the same row");
            }
        }

        setConditionsForRow(clustering, condition);
        hasExists = true;
    }

    public void addConditions(Clustering<?> clustering, Collection<ColumnCondition> conds, QueryOptions options) throws InvalidRequestException
    {
        RowCondition condition = getConditionsForRow(clustering);
        if (condition == null)
        {
            condition = new ColumnsConditions(clustering);
            setConditionsForRow(clustering, condition);
        }
        else if (!(condition instanceof ColumnsConditions))
        {
            throw new InvalidRequestException("Cannot mix IF conditions and " + ((ToCQL) condition).toCQL() + " for the same row");
        }
        ((ColumnsConditions)condition).addConditions(conds, options);
    }

    private RowCondition getConditionsForRow(Clustering<?> clustering)
    {
        return clustering == Clustering.STATIC_CLUSTERING ? staticConditions : conditions.get(clustering);
    }

    private void setConditionsForRow(Clustering<?> clustering, RowCondition condition)
    {
        if (clustering == Clustering.STATIC_CLUSTERING)
        {
            assert staticConditions == null;
            staticConditions = condition;
        }
        else
        {

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Use only one kind of condition per row: either column conditions (IF col=val) or existence conditions (IF EXISTS / IF NOT EXISTS), never both for the same primary key.
  2. If both semantics are needed, split into two statements on different rows or use a single column condition that implies existence (e.g., IF somecol = expected).
  3. In custom code calling CQL3CasRequest, check getConditionsForRow(clustering) instanceof ColumnsConditions before adding more conditions, or create a fresh CQL3CasRequest.

Example fix

// before
UPDATE ks.t SET v=1 WHERE k=1 IF NOT EXISTS; -- combined with
UPDATE ks.t SET v=2 WHERE k=1 IF v=0;       -- same row, mixed kinds
// after
UPDATE ks.t SET v=1 WHERE k=1 IF v=0; -- single column condition only
Defensive patterns

Strategy: validation

Validate before calling

// CQL-level guard: never combine existence and column conditions on the same PK row
boolean hasExists = cql.matches("(?s).*IF\\s+(NOT\\s+)?EXISTS.*");
boolean hasColumnCond = cql.matches("(?s).*IF\\s+[a-zA-Z_][a-zA-Z0-9_]*\\s*(=|<|>|!=|IN|CONTAINS).*");
if (hasExists && hasColumnCond) throw new IllegalArgumentException("Mix IF EXISTS and column conditions only on different rows");

Try / catch

try { session.execute(cql); } catch (InvalidRequestException e) { if (e.getMessage().contains("Cannot mix IF conditions")) { /* split statement or drop one condition kind */ } else throw e; }

Prevention

When it happens

Trigger: Executing an INSERT/UPDATE/DELETE with LWT conditions that combine a plain existence check (IF EXISTS / IF NOT EXISTS) with column-value conditions (e.g., IF col = x) targeting the same primary-key row in one batch or statement flow, so addConditionsTo invokes addConditions twice for the same clustering with mismatched condition types.

Common situations: Hand-building CAS requests in internal code or drivers' LWT builders; batching a conditional INSERT ... IF NOT EXISTS together with UPDATE ... IF col=val on the same row; refactoring statement code that previously applied conditions to different rows.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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