apache/cassandra · error · InvalidRequestException

Invalid empty serial consistency level

Error message

Invalid empty serial consistency level

What it means

For batches, the serial consistency level (used for lightweight-transaction coordination via Paxos) must also be explicitly set. execute() throws InvalidRequestException when options.getSerialConsistency() is null, immediately after the plain consistency check.

Source

Thrown at src/java/org/apache/cassandra/cql3/statements/BatchStatement.java:508

        }
    }


    @Override
    public ResultMessage execute(QueryState queryState, QueryOptions options, Dispatcher.RequestTime requestTime)
    {
        return execute(queryState, BatchQueryOptions.withoutPerStatementVariables(options), requestTime);
    }

    public ResultMessage execute(QueryState queryState, BatchQueryOptions options, Dispatcher.RequestTime requestTime)
    {
        long timestamp = options.getTimestamp(queryState);
        long nowInSeconds = options.getNowInSeconds(queryState);

        if (options.getConsistency() == null)
            throw new InvalidRequestException("Invalid empty consistency level");
        if (options.getSerialConsistency() == null)
            throw new InvalidRequestException("Invalid empty serial consistency level");

        ClientState clientState = queryState.getClientState();
        if (Guardrails.writeConsistencyLevels.enabled(clientState)) // to avoid EnumSet allocation
            Guardrails.writeConsistencyLevels.guard(EnumSet.of(options.getConsistency(),
                                                               options.getSerialConsistency()),
                                                    clientState);

        // resolved once for the whole batch, the guardrail checks are not cheap enough to repeat per statement
        DiskUsageCheck diskUsageCheck = ModificationStatement.diskUsageCheck(clientState);
        if (diskUsageCheck != DiskUsageCheck.NONE)
            for (int i = 0; i < statements.size(); i++)
                statements.get(i).validateDiskUsage(options.forStatement(i), clientState, diskUsageCheck);

        if (hasConditions)
            return executeWithConditions(options, queryState, requestTime);

        if (updatesVirtualTables)
            executeInternalWithoutCondition(queryState, options, requestTime);

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Set the serial consistency explicitly (options.setSerialConsistency(ConsistencyLevel.SERIAL) or LOCAL_SERIAL)
  2. Ensure the driver/client sends the serial consistency field on the BATCH message
  3. Only relevant for LWT batches in practice — populate serial CL defaults in any internal option builder

Example fix

// before
BatchQueryOptions opts = ...; opts.setConsistency(ConsistencyLevel.QUORUM); // serial unset
// after
opts.setConsistency(ConsistencyLevel.QUORUM);
opts.setSerialConsistency(ConsistencyLevel.LOCAL_SERIAL);
Defensive patterns

Strategy: validation

Validate before calling

if (options.getSerialConsistency() == null) options.setSerialConsistency(ConsistencyLevel.SERIAL);

Try / catch

catch (InvalidRequestException e) { if (e.getMessage().contains("serial consistency")) { setDefaultSerialClAndRetry(); } else throw e; }

Prevention

When it happens

Trigger: Executing a batch via execute() with BatchQueryOptions whose serialConsistency was never populated — e.g. conditional (LWT) batches or programmatic callers that set only the regular consistency level.

Common situations: Custom protocol implementations omitting the serial CL field; internal tools constructing query options manually; driver versions with incomplete SERIAL_CL support on batch messages.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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