apache/cassandra · warning

Unlogged batch covering

Error message

Unlogged batch covering {} partitions detected against table{} {}. You should use a logged batch for atomicity, or asynchronous writes for performance.

What it means

Cassandra emits this client warning when an UNLOGGED batch spans more partitions than the configured warn threshold (cassandra.unlogged_batch_across_partitions_warn_threshold, default 10). Unlogged batches are not atomic and give no performance benefit when they touch many partitions, so the coordinator warns instead of failing.

Solutions

  1. Use per-partition batching so each batch touches a single partition key
  2. If atomicity is required, switch the batch to LOGGED (plain BATCH without UNLOGGED)
  3. Replace the multi-partition batch with asynchronous individual writes (driver executeAsync)
  4. Raise or disable the threshold via cassandra.unlogged_batch_across_partitions_warn_threshold only after confirming the access pattern

Example fix

// before
BatchStatement batch = QueryBuilder.batch(ins1, ins2, ins3); // rows in different partitions, unlogged
// after
ins1.executeAsync(); ins2.executeAsync(); ins3.executeAsync(); // or one batch per partition key
Defensive patterns

Strategy: validation

Validate before calling

int distinctPartitions = statements.stream().map(s -> s.partitionKey()).distinct().count();
if (distinctPartitions > 10) throw new IllegalArgumentException("batch spans " + distinctPartitions + " partitions; use async writes or logged batch");

Prevention

When it happens

Trigger: Executing a BATCH (or executeBatch via driver) typed as UNLOGGED whose rows span more distinct partition keys than the warn threshold; verifyBatchType in BatchStatement.executeWithoutConditions raises it via ClientWarn.

Common situations: Bulk-loading with a single unlogged batch instead of per-partition batching; a client framework that turns all inserts into one batch; misconfigured threshold after upgrades; time-series writes with random partition keys.

Understand the failure class

Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.

Related errors


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

Appendix: source

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

            for (IMutation mutation : mutations)
            {
                for (PartitionUpdate update : mutation.getPartitionUpdates())
                {
                    keySet.add(update.partitionKey());

                    tableNames.add(update.metadata().toString());
                }
            }

            // CASSANDRA-11529: log only if we have more than a threshold of keys, this was also suggested in the
            // original ticket that introduced this warning, CASSANDRA-9282
            if (keySet.size() > DatabaseDescriptor.getUnloggedBatchAcrossPartitionsWarnThreshold())
            {
                NoSpamLogger.log(logger, NoSpamLogger.Level.WARN, 1, TimeUnit.MINUTES, UNLOGGED_BATCH_WARNING,
                                 keySet.size(), tableNames.size() == 1 ? "" : "s", tableNames);

                ClientWarn.instance.warn(MessageFormatter.arrayFormat(UNLOGGED_BATCH_WARNING, new Object[]{keySet.size(),
                                                    tableNames.size() == 1 ? "" : "s", tableNames}).getMessage());
            }
        }
    }


    @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)

View on GitHub (pinned to 88fd0f6a0e)