apache/cassandra · error · TombstoneAbortException
TombstoneAbortException
Error message
TombstoneAbortException
What it means
WarningsSnapshot.maybeAbort throws TombstoneAbortException when the coordinator's collected warnings show the query hit the tombstone abort threshold (tombstone_failure_threshold) — too many tombstones encountered while reading. Unlike the warning threshold, the abort threshold fails the read outright to protect nodes from tombstone-heavy scans.
Source
Thrown at src/java/org/apache/cassandra/service/reads/thresholds/WarningsSnapshot.java:110
{
return this != EMPTY;
}
@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);
}
View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Run nodetool compact (or major compaction / repair-assisted) on affected tables to purge tombstones
- Reduce TTL churn or increase compaction throughput so tombstones get purged promptly
- Raise tombstone_failure_threshold / tombstone_warn_threshold in cassandra.yaml only if justified
- Rewrite queries to touch narrower partitions and avoid scanning tombstone-dense ranges
Example fix
// before
$ nodetool compact ks tbl # tombstones still accumulating
// after
ALTER TABLE ks.tbl WITH compaction = {'class':'SizeTieredCompactionStrategy','tombstone_threshold':'0.2'}; Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight: check tombstone density before scanning // shell: nodetool tablehistograms ks tbl — if 'Tombstones per slice' p99 approaches the threshold, compact first
Try / catch
try {
return session.execute(scanQuery);
} catch (e) {
if (e instanceof TombstoneAbortException) {
logger.warn('tombstone abort on query; compacting table and retrying later', e);
scheduleCompaction(keyspace, table);
throw e; // do not blindly retry a doomed scan
}
throw e;
} Prevention
- Monitor tombstone_warn_threshold hits in logs — fix before they become aborts
- Ensure compaction keeps up with delete/TTL churn (tombstone_threshold/tombstone_compaction_interval)
- Avoid unbounded partition scans on churn-heavy tables
- Raise tombstone_failure_threshold only after fixing compaction, not instead of it
When it happens
Trigger: A read command (e.g. big partition scan or filtering query) visits more tombstones than tombstone_failure_threshold (default 100000) across replicas; awaitResults calls maybeAbort and the snapshot contains abort instances.
Common situations: Tables with heavy delete/overwrite churn never compacted; TTL-expired data piling up; queries scanning expired cells with gc_grace not yet elapsed; thresholds too low for legitimately tombstone-heavy workloads.
Related errors
- ReadSizeAbortException
- Read %d live rows and %d tombstone cells for query %1.512s;
- Unsupported disk access mode for compaction_read_disk_access
- concurrent_compactors should be strictly greater than 0, but
- Invalid value of compaction_throughput:
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/1fecce6fa2402ffe.
Report an issue: GitHub.