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
- 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.
- 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).
- 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
- Keep at most one condition kind (existence or column comparison) per primary-key row per CAS request
- When batching LWT statements, ensure conditional statements target distinct rows
- Review driver LWT builder code for repeated addConditions calls on the same clustering key
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
- Invalid null value of timestamp
- A TTL must be greater or equal to 0, but was <ttl>
- ttl is too large. requested (%d) maximum (%d)
- Cannot provide custom timestamp for conditional BATCH
- Counter and non-counter mutations cannot exist in the same b
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/f2909ba76f4d1a20.
Report an issue: GitHub.