{"record":{"id":"6b5c291583292641","repo":"apache/cassandra","slug":"counters-are-not-allowed-inside-tuples","errorCode":null,"errorMessage":"Counters are not allowed inside tuples","messagePattern":"Counters are not allowed inside tuples","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/CQL3Type.java","lineNumber":1092,"sourceCode":"            public RawTuple freeze()\n            {\n                return this;\n            }\n\n            @Override\n            public void validate(ClientState state, String name)\n            {\n                for (CQL3Type.Raw t : types)\n                    t.validate(state, name);\n            }\n\n            public CQL3Type prepare(String keyspace, Types udts) throws InvalidRequestException\n            {\n                List<AbstractType<?>> ts = new ArrayList<>(types.size());\n                for (CQL3Type.Raw t : types)\n                {\n                    if (t.isCounter())\n                        throw new InvalidRequestException(\"Counters are not allowed inside tuples\");\n\n                    ts.add(t.prepare(keyspace, udts).getType());\n                }\n                return new Tuple(new TupleType(ts));\n            }\n\n            public boolean isTuple()\n            {\n                return true;\n            }\n\n            public boolean referencesUserType(String name)\n            {\n                return types.stream().anyMatch(t -> t.referencesUserType(name));\n            }\n\n            @Override\n            public String toString()","sourceCodeStart":1074,"sourceCodeEnd":1110,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/CQL3Type.java#L1074-L1110","documentation":"InvalidRequestException from RawTuple.prepare: one of the element types in a tuple declaration is a counter type. Counters are only permitted in counter tables and cannot appear as tuple components; the prepare loop checks each element with isCounter() before building the TupleType.","triggerScenarios":"Declaring a column like `tuple<int, counter>` in CREATE TABLE / ALTER TABLE, or using counter as a tuple field anywhere in type preparation.","commonSituations":"Trying to bundle a counter with metadata in one tuple column; accidental use of a counter-typed Raw inside tuple field lists.","solutions":["Move the counter to its own top-level column and keep the tuple for non-counter fields","Use bigint (snapshot value) in the tuple instead of counter and update it with read-modify-write if approximate values suffice","Split into two columns: one tuple, one counter"],"exampleFix":"// before\nCREATE TABLE t (id uuid PRIMARY KEY, info tuple<text, counter>);\n// after\nCREATE TABLE t (id uuid PRIMARY KEY, info tuple<text>, hits counter);","handlingStrategy":"validation","validationCode":"boolean usesCounterInTuple(String cqlTypeDecl) {\n    return cqlTypeDecl.toLowerCase().replaceAll(\"\\\\s+\",\"\").matches(\"tuple<.*counter.*\");\n}","typeGuard":null,"tryCatchPattern":"try { session.execute(ddl); } catch (InvalidQueryException e) { if (e.getMessage().equals(\"Counters are not allowed inside tuples\")) { /* split counter into its own column */ } else throw e; }","preventionTips":["Keep counters out of composite/tuple/collection types entirely","Use a separate counter column next to the tuple","Use bigint in tuples only for snapshot values written non-incrementally"],"tags":["cql","schema","counter","tuple"],"backgroundTag":"schema-validation-failed","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"}