{"record":{"id":"688aa32d98de5c47","repo":"apache/cassandra","slug":"mutations-for-virtual-and-regular-tables-cannot-ex","errorCode":null,"errorMessage":"Mutations for virtual and regular tables cannot exist in the same batch","messagePattern":"Mutations for virtual and regular tables cannot exist in the same batch","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/statements/BatchStatement.java","lineNumber":306,"sourceCode":"        }\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        {\n            String ksName = null;\n            String cfName = null;\n            for (ModificationStatement stmt : statements)\n            {\n                if (ksName != null && (!stmt.keyspace().equals(ksName) || !stmt.table().equals(cfName)))\n                    throw new InvalidRequestException(\"Batch with conditions cannot span multiple tables: \" + stmt.source);\n                ksName = stmt.keyspace();\n                cfName = stmt.table();\n            }\n        }\n    }\n","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java#L288-L324","documentation":"A single batch cannot contain mutations targeting both virtual tables and regular tables; the two write paths are incompatible. validate() flags the combination of hasVirtualTables && hasRegularTables and rejects the batch.","triggerScenarios":"A BATCH mixing e.g. 'UPDATE system_views.x ...' with 'INSERT INTO my_keyspace.my_table ...'.","commonSituations":"Generated or templated batches that iterate a table list containing both virtual and regular tables; tooling that doesn't distinguish virtual tables.","solutions":["Issue separate statements/batches for virtual and regular table operations","Filter virtual tables out of batch-building code paths (query system_schema / metadata to detect them)","Remember virtual tables are effectively read-only; remove those mutations entirely"],"exampleFix":"// before\nBEGIN BATCH INSERT INTO ks.t ...; UPDATE system_views.v ...; APPLY BATCH;\n// after\nINSERT INTO ks.t ...; -- virtual table mutation removed\n","handlingStrategy":"validation","validationCode":"boolean anyVirtual = stmts.stream().anyMatch(s -> s.getTable().isVirtual());\nboolean anyRegular = stmts.stream().anyMatch(s -> !s.getTable().isVirtual());\nif (anyVirtual && anyRegular) throw new IllegalArgumentException(\"Separate virtual and regular table writes\");","typeGuard":"boolean isVirtualTable(TableMetadata tm) { return tm.isVirtual(); }","tryCatchPattern":"catch (InvalidRequestException e) { if (e.getMessage().contains(\"virtual and regular\")) { partitionStatementsByKindAndRetry(); } else throw e; }","preventionTips":["Filter virtual tables out at the data-source layer before any batching","Treat virtual tables as read-only everywhere in your codebase"],"tags":["cql","batch","virtual-tables"],"backgroundTag":"mutually-exclusive-options","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"}