apache/cassandra · warning
Read %d live rows and %d tombstone cells for query %1.512s;
Error message
Read %d live rows and %d tombstone cells for query %1.512s; token %s (see tombstone_warn_threshold)
What it means
When a read command completes, Cassandra counts tombstone cells; if the count exceeds tombstone_warn_threshold it logs and warns the client that the query read many tombstones, including the CQL text and scanned token. Exceeding tombstone_failure_threshold escalates to a TombstoneOverwhelmingException; this warning is the earlier, non-fatal signal of expensive tombstone scans.
Source
Thrown at src/java/org/apache/cassandra/db/ReadCommand.java:739
@Override
public void onClose()
{
recordLatency(metric, nanoTime() - startTimeNanos);
metric.tombstoneScannedHistogram.update(tombstones);
metric.liveScannedHistogram.update(liveRows);
metric.totalRowsRead.inc(liveRows);
boolean warnTombstones = tombstones > warningThreshold && respectTombstoneThresholds;
if (warnTombstones)
{
String msg = String.format(
"Read %d live rows and %d tombstone cells for query %1.512s; token %s (see tombstone_warn_threshold)",
liveRows, tombstones, ReadCommand.this.toCQLString(), currentKey.getToken());
if (trackWarnings)
MessageParams.add(ParamType.TOMBSTONE_WARNING, tombstones);
else
ClientWarn.instance.warn(msg);
if (tombstones < failureThreshold)
{
metric.tombstoneWarnings.inc();
}
logger.warn(msg);
}
Tracing.trace("Read {} live rows and {} tombstone cells{}",
liveRows, tombstones,
(warnTombstones ? " (see tombstone_warn_threshold)" : ""));
}
}
return Transformation.apply(iter, new MetricRecording());
}
private boolean shouldTrackSize(DataStorageSpec.LongBytesBound warnThresholdBytes, DataStorageSpec.LongBytesBound abortThresholdBytes)View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Rewrite the query to be more selective (narrow partition/clustering ranges) so fewer tombstones are scanned.
- Run compaction (or alter compaction strategy, e.g. DTCS/TWCS for TTL data) to purge accumulated tombstones.
- Raise tombstone_warn_threshold in cassandra.yaml only after confirming the read cost is acceptable.
- Check for application patterns issuing repeated range deletes/overwrites and reduce them.
Example fix
// before SELECT * FROM ks.events; // scans whole partitions incl. tombstones // after SELECT * FROM ks.events WHERE day = '2026-09-10' AND bucket = 3;
Defensive patterns
Strategy: validation
Validate before calling
// keep expected scan cost under tombstone_warn_threshold
long approxCells = estimatedPartitionCells(partitionKey); // from your data model
if (approxCells > 1000) throw new IllegalArgumentException("query would scan too many tombstones; narrow it"); Prevention
- Model data to avoid dense delete/overwrite patterns that leave tombstones.
- Use TWCS/DTCS for TTL-heavy tables and keep gc_grace compaction running.
- Monitor the TableMetrics tombstoneWarnings metric and tune queries, not just thresholds.
When it happens
Trigger: Any SELECT whose coordinator processes more live/tombstone cells than tombstone_warn_threshold (default 1000) during local execution onClose; the warning is sent via ClientWarn when warning tracking is off.
Common situations: Wide-partition deletes leaving many tombstones; queries scanning dead cells from expired TTL data; non-sstable-scanner queries over heavily mutated partitions; compacted-pending data.
Related errors
- TombstoneAbortException
- Unsupported disk access mode for compaction_read_disk_access
- concurrent_compactors should be strictly greater than 0, but
- Invalid value of compaction_throughput:
- write_tombstone_warn_threshold (%d) must be -1 (disabled) or
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/e03c27fcb7daeb87.
Report an issue: GitHub.