apache/cassandra · critical · CorruptIndexException
The postings position is less than zero.
Error message
The postings position is less than zero.
What it means
Thrown as a CorruptIndexException when the SAI segment metadata records a negative root position for the POSTING_LISTS component of a numeric index segment. Segment component positions are file offsets into the component files and must never be negative, so a negative value means the metadata was written corruptly or the segment file/metadata pairing is inconsistent. It deliberately names BALANCED_TREE in the component field even when the postings position is the offender, an upstream quirk.
Source
Thrown at src/java/org/apache/cassandra/index/sai/disk/v1/segment/NumericIndexSegmentSearcher.java:66
{
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private final BlockBalancedTreeReader treeReader;
private final QueryEventListener.BalancedTreeEventListener perColumnEventListener;
NumericIndexSegmentSearcher(PrimaryKeyMap.Factory primaryKeyMapFactory,
PerColumnIndexFiles perIndexFiles,
SegmentMetadata segmentMetadata,
StorageAttachedIndex index) throws IOException
{
super(primaryKeyMapFactory, perIndexFiles, segmentMetadata, index);
final long treePosition = metadata.getIndexRoot(IndexComponent.BALANCED_TREE);
if (treePosition < 0)
throw new CorruptIndexException(index.identifier().logMessage("The tree position is less than zero."), IndexComponent.BALANCED_TREE.name);
final long postingsPosition = metadata.getIndexRoot(IndexComponent.POSTING_LISTS);
if (postingsPosition < 0)
throw new CorruptIndexException(index.identifier().logMessage("The postings position is less than zero."), IndexComponent.BALANCED_TREE.name);
treeReader = new BlockBalancedTreeReader(index.identifier(),
indexFiles.balancedTree(),
treePosition,
indexFiles.postingLists(),
postingsPosition);
perColumnEventListener = (QueryEventListener.BalancedTreeEventListener)index.columnQueryMetrics();
}
@Override
public long indexFileCacheSize()
{
return treeReader.memoryUsage();
}
@Override
public KeyRangeIterator search(Expression exp, AbstractBounds<PartitionPosition> keyRange, QueryContext context) throws IOException
{View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Run nodetool scrubs/rebuild of the affected SSTables (or REBUILD the secondary index) so the segment is rewritten with valid metadata
- Validate the segment file and metadata pairing (matching generation numbers) and restore from a good backup if files were moved manually
- Check the storage medium/filesystem for corruption (dmesg, fsck)
- If reproducible, file a bug with the segment metadata contents; the check should report the component it validated
Example fix
// before
if (postingsPosition < 0)
throw new CorruptIndexException(index.identifier().logMessage("The postings position is less than zero."), IndexComponent.BALANCED_TREE.name);
// after
if (postingsPosition < 0)
throw new CorruptIndexException(index.identifier().logMessage("The postings position is less than zero."), IndexComponent.POSTING_LISTS.name); Defensive patterns
Strategy: validation
Validate before calling
SegmentMetadata meta = readSegmentMetadata(...);
if (meta.getIndexRoot(IndexComponent.POSTING_LISTS) < 0 || meta.getIndexRoot(IndexComponent.BALANCED_TREE) < 0)
throw new CorruptIndexException("negative component root in " + index.identifier(), "segment"); Type guard
boolean hasValidRoots(SegmentMetadata m) {
return m.getIndexRoot(IndexComponent.BALANCED_TREE) >= 0 && m.getIndexRoot(IndexComponent.POSTING_LISTS) >= 0;
} Prevention
- Never move or copy individual index component files; treat a segment's components as an atomic set
- Run scrub/rebuild after suspected crashes before reopening indexes
- Monitor for CorruptIndexException in logs and rebuild indexes proactively
- Keep node versions consistent across the cluster
When it happens
Trigger: Opening a numeric SAI segment whose SegmentMetadata contains IndexComponent.POSTING_LISTS root < 0, e.g. after a corrupted flush, truncated SSTable components, or manually edited/copied index files.
Common situations: Disk corruption or incomplete flush during crash, restoring index files from a backup taken mid-flush, mixing segment files from different generations, or running a Cassandra version against index files written by an incompatible one.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- Index should be between [0, %d), but was %d.
- The target point id [%d] cannot be less than 0 or greater th
- Invalid block offset %d for postings block idx %d
- Postings list #%s block is corrupted. Bits per value should
- The tree position is less than zero.
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/51c22c129fa42f90.
Report an issue: GitHub.