{"record":{"id":"38b05259fe6588c8","repo":"apache/cassandra","slug":"invalid-null-value-for-counter-increment","errorCode":null,"errorMessage":"Invalid null value for counter increment","messagePattern":"Invalid null value for counter increment","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/terms/Constants.java","lineNumber":520,"sourceCode":"    public static class Adder extends Operation\n    {\n        public Adder(ColumnMetadata column, Term t)\n        {\n            super(column, t);\n        }\n\n        public boolean requiresRead()\n        {\n            return !(column.type instanceof CounterColumnType);\n        }\n\n        public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException\n        {\n            if (column.type instanceof CounterColumnType)\n            {\n                ByteBuffer bytes = t.bindAndGet(builder);\n                if (bytes == null)\n                    throw new InvalidRequestException(\"Invalid null value for counter increment\");\n                if (bytes == ByteBufferUtil.UNSET_BYTE_BUFFER)\n                    return;\n\n                long increment = ByteBufferUtil.toLong(bytes);\n                builder.addCounter(column, increment);\n            }\n            else if (column.type instanceof NumberType<?>)\n            {\n                @SuppressWarnings(\"unchecked\") NumberType<Number> type = (NumberType<Number>) column.type;\n                ByteBuffer increment = type.sanitize(t.bindAndGet(builder));\n                if (increment == null)\n                    return;\n                ByteBuffer current = type.sanitize(getCurrentCellBuffer(column, partitionKey, builder));\n                if (current == null)\n                    return;\n                ByteBuffer newValue = type.add(type.compose(current), type.compose(increment));\n                builder.addCell(column, newValue);\n            }","sourceCodeStart":502,"sourceCodeEnd":538,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/terms/Constants.java#L502-L538","documentation":"Thrown at execution time when a counter increment (Stats.Setter/increment path) binds to null. Like the literal case, counters have no null value: the delta must be a concrete long, so a null bind marker result is rejected.","triggerScenarios":"`UPDATE t SET c = c + ?` executed with the parameter bound to null (driver `unset` vs null distinction: null is rejected, unset is skipped).","commonSituations":"Nullable counter-delta fields in application DTOs; batch builders that add statements with null values by default; missing request data in APIs that map straight to CQL binds.","solutions":["Bind a non-null long, defaulting to 0 when no delta applies","Omit the counter update (or the whole statement) when the delta is unknown","Use ByteBufferUtil.UNSET semantics via the driver's unset value if the column should be skipped, not null"],"exampleFix":"// before\nps.bind(0, delta); // delta may be null\n// after\nps.bind(0, delta == null ? 0L : delta);","handlingStrategy":"validation","validationCode":"Objects.requireNonNull(delta, \"counter increment must not be null\");","typeGuard":null,"tryCatchPattern":"try { session.execute(ps.bind(delta)); } catch (InvalidQueryException e) { if (e.getMessage().contains(\"Invalid null value for counter increment\")) { /* default to 0 or skip */ } else throw e; }","preventionTips":["Null-check delta before binding","Use Optional<Long> and skip statements for empty values","Distinguish driver unset (skip) from null (rejected)"],"tags":["cql","counter","null-value","bind-parameter"],"backgroundTag":"null-argument","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}