{"record":{"id":"f2909ba76f4d1a20","repo":"apache/cassandra","slug":"cannot-mix-if-conditions-and-s-for-the-same-row","errorCode":null,"errorMessage":"Cannot mix IF conditions and %s for the same row","messagePattern":"Cannot mix IF conditions and (.+?) for the same row","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/statements/CQL3CasRequest.java","lineNumber":209,"sourceCode":"                    : new InvalidRequestException(\"Cannot mix IF conditions and IF \" + (isNotExist ? \"NOT \" : \"\") + \"EXISTS for the same row\");\n            }\n        }\n\n        setConditionsForRow(clustering, condition);\n        hasExists = true;\n    }\n\n    public void addConditions(Clustering<?> clustering, Collection<ColumnCondition> conds, QueryOptions options) throws InvalidRequestException\n    {\n        RowCondition condition = getConditionsForRow(clustering);\n        if (condition == null)\n        {\n            condition = new ColumnsConditions(clustering);\n            setConditionsForRow(clustering, condition);\n        }\n        else if (!(condition instanceof ColumnsConditions))\n        {\n            throw new InvalidRequestException(\"Cannot mix IF conditions and \" + ((ToCQL) condition).toCQL() + \" for the same row\");\n        }\n        ((ColumnsConditions)condition).addConditions(conds, options);\n    }\n\n    private RowCondition getConditionsForRow(Clustering<?> clustering)\n    {\n        return clustering == Clustering.STATIC_CLUSTERING ? staticConditions : conditions.get(clustering);\n    }\n\n    private void setConditionsForRow(Clustering<?> clustering, RowCondition condition)\n    {\n        if (clustering == Clustering.STATIC_CLUSTERING)\n        {\n            assert staticConditions == null;\n            staticConditions = condition;\n        }\n        else\n        {","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/statements/CQL3CasRequest.java#L191-L227","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nUPDATE ks.t SET v=1 WHERE k=1 IF NOT EXISTS; -- combined with\nUPDATE ks.t SET v=2 WHERE k=1 IF v=0;       -- same row, mixed kinds\n// after\nUPDATE ks.t SET v=1 WHERE k=1 IF v=0; -- single column condition only","handlingStrategy":"validation","validationCode":"// CQL-level guard: never combine existence and column conditions on the same PK row\nboolean hasExists = cql.matches(\"(?s).*IF\\\\s+(NOT\\\\s+)?EXISTS.*\");\nboolean hasColumnCond = cql.matches(\"(?s).*IF\\\\s+[a-zA-Z_][a-zA-Z0-9_]*\\\\s*(=|<|>|!=|IN|CONTAINS).*\");\nif (hasExists && hasColumnCond) throw new IllegalArgumentException(\"Mix IF EXISTS and column conditions only on different rows\");","typeGuard":null,"tryCatchPattern":"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; }","preventionTips":["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"],"tags":["cql","lwt","invalid-request"],"backgroundTag":"conflicting-config-options","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}