{"record":{"id":"c5f7276f30a0b1bb","repo":"apache/cassandra","slug":"invalid-operation-s-for-non-counter-column-s","errorCode":null,"errorMessage":"Invalid operation (%s) for non counter column %s","messagePattern":"Invalid operation \\((.+?)\\) for non counter column (.+?)","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/Operation.java","lineNumber":347,"sourceCode":"            this.value = value;\n        }\n\n        public Operation prepare(TableMetadata metadata, ColumnMetadata receiver, boolean canReadExistingState) throws InvalidRequestException\n        {\n            if (!(receiver.type instanceof CollectionType))\n            {\n                if (receiver.type instanceof TupleType)\n                    throw new InvalidRequestException(String.format(\"Invalid operation (%s) for tuple column %s\", toString(receiver), receiver.name));\n\n                if (canReadExistingState)\n                {\n                    if (!(receiver.type instanceof NumberType<?>) && !(receiver.type instanceof StringType))\n                        throw new InvalidRequestException(String.format(\"Invalid operation (%s) for non-numeric and non-text type %s\", toString(receiver), receiver.name));\n                }\n                else\n                {\n                    if (!(receiver.type instanceof CounterColumnType))\n                        throw new InvalidRequestException(String.format(\"Invalid operation (%s) for non counter column %s\", toString(receiver), receiver.name));\n                }\n                return new Constants.Adder(receiver, value.prepare(metadata.keyspace, receiver));\n            }\n            else if (!(receiver.type.isMultiCell()))\n                throw new InvalidRequestException(String.format(\"Invalid operation (%s) for frozen collection column %s\", toString(receiver), receiver.name));\n\n            switch (((CollectionType<?>)receiver.type).kind)\n            {\n                case LIST:\n                    return new Lists.Appender(receiver, value.prepare(metadata.keyspace, receiver));\n                case SET:\n                    return new Sets.Adder(receiver, value.prepare(metadata.keyspace, receiver));\n                case MAP:\n                    Term term;\n                    try\n                    {\n                        term = value.prepare(metadata.keyspace, receiver);\n                    }","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/Operation.java#L329-L365","documentation":"Cassandra throws this during preparation when an increment operation (col = col + value) is issued against a non-counter column in a context where existing state cannot be read (counter-table semantics path, canReadExistingState=false). In that mode only CounterColumnType is legal; all other types are rejected.","triggerScenarios":"Using 'UPDATE t SET mycol = mycol + 1' on a column that is not of type counter in a table where the adder requires counter semantics; e.g. incrementing an int column while relying on read-modify-write-free counter syntax.","commonSituations":"Developer confuses int/bigint columns with counter columns; counter tables (insert-not-allowed) where only CounterColumnType columns may use '+='; schema changed from counter to another numeric type, breaking existing update code.","solutions":["Declare the column as counter type if atomic increments are needed (counter columns require a dedicated table design: no non-counter primary-key-other columns updates)","Otherwise use a regular numeric column and do read-then-write assignment","Migrate schema correctly: counters cannot be altered to/from other types; create a new column/table","Fix the query generator to emit increments only for counter columns"],"exampleFix":"// before (views int)\nUPDATE stats SET views = views + 1 WHERE id = 1;  -- views is int, not counter\n// after\nUPDATE stats SET views = 43 WHERE id = 1;  -- read-modify-write, or make views counter","handlingStrategy":"validation","validationCode":"AbstractType<?> t = tm.getColumn(col).getType();\nif (!(t instanceof CounterColumnType))\n    throw new IllegalArgumentException(col + \" is not a counter; use read-then-write assignment\");","typeGuard":"boolean isCounter(AbstractType<?> t) { return t instanceof CounterColumnType; }","tryCatchPattern":"try { session.execute(increment); } catch (InvalidRequestException e) { if (e.getMessage().contains(\"non counter column\")) doReadModifyWrite(); else throw e; }","preventionTips":["Explicitly model counter columns; emit increments only for them","Remember counter columns need dedicated table design and cannot be ALTERed to other types","Review migrations that changed counter columns to scalars"],"tags":["cql","cassandra","counter","type-mismatch"],"backgroundTag":"type-mismatch","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"}