apache/cassandra · error · InvalidRequestException

Invalid null value for counter increment/decrement

Error message

Invalid null value for counter increment/decrement

What it means

Thrown when a NULL literal (or a bind variable bound to null) is prepared as the value of a counter increment/decrement. Counters cannot be set to null; every counter mutation must supply a numeric delta, so the CQL layer rejects the assignment during statement preparation before execution.

Solutions

  1. Ensure the bound value for the counter delta is a non-null long before executing
  2. Coalesce null deltas to 0 in application code, or skip the counter update clause entirely when the delta is absent
  3. If the intent is to reset the counter, remember counters cannot be set/reset to a value or null — delete the counter row/column instead

Example fix

// before
Long delta = getDelta(); // may be null
session.execute("UPDATE counts SET c = c + ?", delta);
// after
Long delta = getDelta();
if (delta != null)
    session.execute("UPDATE counts SET c = c + ?", delta);
Defensive patterns

Strategy: validation

Validate before calling

if (delta == null) throw new IllegalArgumentException("counter delta must not be null");

Try / catch

try { session.execute(stmt); } catch (InvalidQueryException e) { if (e.getMessage().contains("Invalid null value for counter")) { /* supply default or skip */ } else throw e; }

Prevention

When it happens

Trigger: Issuing `UPDATE t SET c = c + null` or `SET c = c - null` on a counter column, or executing a prepared statement `UPDATE t SET c = c + ?` with a null bound to the marker.

Common situations: Application code builds increments from optional/nullable values and forgets a default; an ORM or driver binds null when a delta field is absent; refactors turn a literal increment into a nullable parameter.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/95bd6173828e8276. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/cql3/terms/Constants.java:202

        }

        public AbstractType<?> getExactTypeIfKnown(String keyspace)
        {
            return null;
        }
    }

    // We don't have "unset" literal in the syntax, but it's used implicitely for JSON "DEFAULT UNSET" option
    public static final UnsetLiteral UNSET_LITERAL = new UnsetLiteral();

    public static final Value UNSET_VALUE = new Value(ByteBufferUtil.UNSET_BYTE_BUFFER);

    private static class NullLiteral extends Term.Raw
    {
        public Term prepare(String keyspace, ColumnSpecification receiver) throws InvalidRequestException
        {
            if (!testAssignment(keyspace, receiver).isAssignable())
                throw new InvalidRequestException("Invalid null value for counter increment/decrement");

            return NULL_VALUE;
        }

        public AssignmentTestable.TestResult testAssignment(String keyspace, ColumnSpecification receiver)
        {
            return receiver.type instanceof CounterColumnType
                 ? AssignmentTestable.TestResult.NOT_ASSIGNABLE
                 : AssignmentTestable.TestResult.WEAKLY_ASSIGNABLE;
        }

        public String getText()
        {
            return "NULL";
        }

        public AbstractType<?> getExactTypeIfKnown(String keyspace)
        {

View on GitHub (pinned to 88fd0f6a0e)