apache/cassandra · error · InvalidRequestException

NODE_LOCAL consistency level can only be used with BATCH…

Error message

NODE_LOCAL consistency level can only be used with BATCH, UPDATE, INSERT, DELETE, and SELECT statements

What it means

Even when enabled, NODE_LOCAL consistency is only implemented for BatchStatement, ModificationStatement (INSERT/UPDATE/DELETE), SelectStatement, and TransactionStatement. Any other statement type executed with NODE_LOCAL falls through to this InvalidRequestException.

Solutions

  1. Use a standard consistency level for non-DML statements.
  2. Restrict NODE_LOCAL to BATCH/UPDATE/INSERT/DELETE/SELECT statements only.

Example fix

// before
session.execute("CREATE TABLE t (...)").setConsistencyLevel(NODE_LOCAL); // fails
// after
session.execute("CREATE TABLE t (...)").setConsistencyLevel(LOCAL_QUORUM);
Defensive patterns

Strategy: validation

Validate before calling

boolean nodeLocalAllowed = stmt instanceof BatchStatement || stmt instanceof ModificationStatement || stmt instanceof SelectStatement || stmt instanceof TransactionStatement; if (usesNodeLocal && !nodeLocalAllowed) throw new IllegalStateException("NODE_LOCAL not supported for this statement type");

Try / catch

try { session.execute(stmt); } catch (InvalidRequestException e) { if (e.getMessage().contains("can only be used with BATCH")) { /* switch CL for DDL */ } }

Prevention

When it happens

Trigger: Running e.g. CREATE TABLE, ALTER, or other DDL/utility statements with consistency level NODE_LOCAL while enable_nodelocal_queries=true.

Common situations: Test harnesses setting NODE_LOCAL globally for all statements and then running schema statements; scripts that set the CL per-session rather than per-query.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/cql3/QueryProcessor.java:329

                             ? processNodeLocalStatement(statement, queryState, options)
                             : statement.execute(queryState, options, requestTime);

        return result == null ? new ResultMessage.Void() : result;
    }

    private ResultMessage processNodeLocalStatement(CQLStatement statement, QueryState queryState, QueryOptions options)
    {
        if (!ENABLE_NODELOCAL_QUERIES.getBoolean())
            throw new InvalidRequestException("NODE_LOCAL consistency level is highly dangerous and should be used only for debugging purposes");

        if (statement instanceof BatchStatement || statement instanceof ModificationStatement)
            return processNodeLocalWrite(statement, queryState, options);
        else if (statement instanceof SelectStatement)
            return processNodeLocalSelect((SelectStatement) statement, queryState, options);
        else if (statement instanceof TransactionStatement)
            return statement.executeLocally(queryState, options);
        else
            throw new InvalidRequestException("NODE_LOCAL consistency level can only be used with BATCH, UPDATE, INSERT, DELETE, and SELECT statements");
    }

    private ResultMessage processNodeLocalWrite(CQLStatement statement, QueryState queryState, QueryOptions options)
    {
        ClientRequestMetrics levelMetrics = ClientRequestsMetricsHolder.writeMetricsForLevel(ConsistencyLevel.NODE_LOCAL);
        ClientRequestMetrics globalMetrics = ClientRequestsMetricsHolder.writeMetrics;

        long startTime = nanoTime();
        try
        {
            return statement.executeLocally(queryState, options);
        }
        finally
        {
            long latency = nanoTime() - startTime;
             levelMetrics.addNano(latency);
            globalMetrics.addNano(latency);
        }

View on GitHub (pinned to 88fd0f6a0e)