apache/cassandra · error · ReadSizeAbortException

ReadSizeAbortException

Error message

ReadSizeAbortException

What it means

WarningsSnapshot.maybeAbort throws ReadSizeAbortException when the accumulated read material exceeds an abort threshold: either local read size (bytes of local reads) or row index-read size. The read is aborted server-side to prevent unbounded memory/CPU consumption on oversized reads.

Source

Thrown at src/java/org/apache/cassandra/service/reads/thresholds/WarningsSnapshot.java:114

    @VisibleForTesting
    WarningsSnapshot merge(WarningsSnapshot other)
    {
        if (other == null || other == EMPTY)
            return this;
        return WarningsSnapshot.create(tombstones.merge(other.tombstones),
                                       localReadSize.merge(other.localReadSize),
                                       rowIndexReadSize.merge(other.rowIndexReadSize),
                                       indexReadSSTablesCount.merge(other.indexReadSSTablesCount));
    }

    public void maybeAbort(ReadCommand command, ConsistencyLevel cl, int received, int blockFor, boolean isDataPresent, Map<InetAddressAndPort, RequestFailureReason> failureReasonByEndpoint)
    {
        if (!tombstones.aborts.instances.isEmpty())
            throw new TombstoneAbortException(tombstoneAbortMessage(tombstones.aborts.instances.size(), tombstones.aborts.maxValue, command.toCQLString()), tombstones.aborts.instances.size(), tombstones.aborts.maxValue, isDataPresent,
                                              cl, received, blockFor, failureReasonByEndpoint);

        if (!localReadSize.aborts.instances.isEmpty())
            throw new ReadSizeAbortException(localReadSizeAbortMessage(localReadSize.aborts.instances.size(), localReadSize.aborts.maxValue, command.toCQLString()),
                                             cl, received, blockFor, isDataPresent, failureReasonByEndpoint);

        if (!rowIndexReadSize.aborts.instances.isEmpty())
            throw new ReadSizeAbortException(rowIndexReadSizeAbortMessage(rowIndexReadSize.aborts.instances.size(), rowIndexReadSize.aborts.maxValue, command.toCQLString()),
                                             cl, received, blockFor, isDataPresent, failureReasonByEndpoint);

        if (!indexReadSSTablesCount.aborts.instances.isEmpty())
            throw new QueryReferencesTooManyIndexesAbortException(tooManyIndexesReadAbortMessage(indexReadSSTablesCount.aborts.instances.size(), indexReadSSTablesCount.aborts.maxValue, command.toCQLString()),
                                                                  indexReadSSTablesCount.aborts.instances.size(),
                                                                  indexReadSSTablesCount.aborts.maxValue,
                                                                  isDataPresent,
                                                                  cl, received, blockFor, failureReasonByEndpoint);
    }

    @VisibleForTesting
    public static String tombstoneAbortMessage(int nodes, long tombstones, String cql)
    {
        return String.format("%s nodes scanned over %s tombstones and aborted the query %s (see tombstone_failure_threshold)", nodes, tombstones, cql);

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Split the read: use token/partition ranges or LIMIT and paginate instead of reading a whole huge partition
  2. Raise local_read_size_fail_threshold / row_index_read_size_fail_threshold in cassandra.yaml if the reads are legitimate
  3. Redesign the data model to bucket large partitions into smaller ones
  4. Enable tracing on the query to see which partition/read triggers the size abort, then target that partition

Example fix

// before
SELECT * FROM ks.events WHERE id = 'big-partition';
// after
SELECT * FROM ks.events WHERE id = 'big-partition' AND bucket = 3;  // bucketed partition
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight: check partition size before a full read
// shell: nodetool tablehistograms ks tbl  — 'Partition size' p99 above local_read_size_warn_threshold signals risk

Try / catch

try {
  return session.execute(widePartitionQuery);
} catch (e) {
  if (e instanceof ReadSizeAbortException) {
    logger.warn('read size abort; falling back to paginated/ranged read', e);
    return paginatedRead(query, pageSize); // fallback strategy
  }
  throw e;
}

Prevention

When it happens

Trigger: A read command's local read bytes exceed local_read_size_abort_threshold, or row-index lookups exceed row_index_read_size_abort_threshold (e.g. querying a huge partition or doing many row-index jumps); awaitResults invokes maybeAbort with abort instances recorded.

Common situations: Single very large partitions (MBs/GBs) queried fully; thousands of rows fetched via secondary index; defaults too strict after upgrading (thresholds added in newer versions); analytics-style batch reads on wide partitions.

Related errors


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