{"record":{"id":"2311bf31928bd37f","repo":"apache/cassandra","slug":"cannot-include-non-counter-statement-in-a-counter","errorCode":null,"errorMessage":"Cannot include non-counter statement in a counter batch","messagePattern":"Cannot include non-counter statement in a counter batch","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/statements/BatchStatement.java","lineNumber":294,"sourceCode":"            if (timestampSet && statement.isTimestampSet())\n                throw new InvalidRequestException(\"Timestamp must be set either on BATCH or individual statements: \" + statement.source);\n\n            if (statement.isCounter())\n                hasCounters = true;\n            else\n                hasNonCounters = true;\n\n            if (statement.isVirtual())\n                hasVirtualTables = true;\n            else\n                hasRegularTables = true;\n        }\n\n        if (timestampSet && hasCounters)\n            throw new InvalidRequestException(\"Cannot provide custom timestamp for a BATCH containing counters\");\n\n        if (isCounter() && hasNonCounters)\n            throw new InvalidRequestException(\"Cannot include non-counter statement in a counter batch\");\n\n        if (hasCounters && hasNonCounters)\n            throw new InvalidRequestException(\"Counter and non-counter mutations cannot exist in the same batch\");\n\n        if (isLogged() && hasCounters)\n            throw new InvalidRequestException(\"Cannot include a counter statement in a logged batch\");\n\n        if (isLogged() && hasVirtualTables)\n            throw new InvalidRequestException(\"Cannot include a virtual table statement in a logged batch\");\n\n        if (hasVirtualTables && hasRegularTables)\n            throw new InvalidRequestException(\"Mutations for virtual and regular tables cannot exist in the same batch\");\n\n        if (hasConditions && hasVirtualTables)\n            throw new InvalidRequestException(\"Conditional BATCH statements cannot include mutations for virtual tables\");\n\n        if (hasConditions)\n        {","sourceCodeStart":276,"sourceCodeEnd":312,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java#L276-L312","documentation":"InvalidRequestException from BatchStatement.validate: the batch was declared/typed as a counter batch (COUNTER BATCH) but contains at least one statement targeting a non-counter table. validate() accumulates hasCounters/hasNonCounters flags per statement; the isCounter() && hasNonCounters combination triggers this guard.","triggerScenarios":"BEGIN BATCH ... where the batch was detected as a counter batch (all/marked counter) yet includes at least one statement against a non-counter table, via execute or prepare.","commonSituations":"Accidentally adding a regular-table write to a batch of counter increments; table schema changed from counter to regular (or vice versa) so statements no longer agree.","solutions":["Move the non-counter statement(s) into a separate batch","Verify table schemas — ensure all batched statements target counter tables when writing counters"],"exampleFix":"// before\nBEGIN BATCH UPDATE ctr SET c=c+1 WHERE k='a'; INSERT INTO t (k,v) VALUES (1,'x'); APPLY BATCH;\n// after\nBEGIN BATCH UPDATE ctr SET c=c+1 WHERE k='a'; APPLY BATCH;\nINSERT INTO t (k,v) VALUES (1,'x');","handlingStrategy":"validation","validationCode":"boolean counterBatch = statements.stream().allMatch(ModificationStatement::isCounter);\nboolean mixed = statements.stream().anyMatch(s -> s.isCounter() != counterBatch);\nif (mixed) throw new IllegalArgumentException(\"counter and non-counter statements must not share a batch\");","typeGuard":null,"tryCatchPattern":"try { session.execute(batch); }\ncatch (InvalidQueryException e) {\n    if (e.getMessage().contains(\"non-counter statement in a counter batch\")) { /* partition statements by table type */ }\n}","preventionTips":["Group batched statements by table type before building batches","Verify target tables are COUNTER type when generating counter batches"],"tags":["cql","batch","counters"],"backgroundTag":"invalid-argument-value","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}