apache/cassandra · warning
Data file partition position
Error message
Data file partition position %d differs from index file row position %d
What it means
During BTI scrub, when both the data file and the index are readable, the scrubber compares the partition's start position in the data file (dataStart) against the position recorded in the index (dataStartFromIndex). If they differ, the index and data are out of sync; the scrubber logs this warning but keeps going, relying on later consistency checks and retry logic to handle the bad partition.
Solutions
- Let the scrub continue; it tracks mismatches and can retry/skip affected partitions.
- After scrub, compact the table to produce a consistent data+index pair.
- Verify the sstable set is intact and matched: do not copy .db component files independently across generation directories.
- If mismatches are widespread, restore the sstables from backup and run `nodetool repair`.
Example fix
// Preventive operational fix: keep data+index components together // before: rsync only *-Data.db between snapshot dirs // after: copy the whole sstable component set (Data.db, Index.db, etc.) from one snapshot
Defensive patterns
Strategy: validation
Validate before calling
// Ensure data and index belong to the same sstable generation before restore $ ls data/ks/tbl-<uuid>/ # copy the FULL component set xx-* (Data.db, Index.db, Statistics.db, TOC.txt) # Never mix components from different generations (different numeric prefixes)
Prevention
- Restore sstables only from consistent snapshots.
- Never manually edit, truncate, or reorder sstable component files.
- Freeze the node (flush or snapshot) before touching sstable files on disk.
- After restores, run nodetool verify before bringing the node back into service.
When it happens
Trigger: `nodetool scrub` on a BTI sstable where an index entry's recorded data offset no longer matches the actual partition offset in the data file — e.g. the data file was altered, truncated, or the index was written against different content.
Common situations: Sstable data and index files mixed from different compaction generations (files copied/replaced independently); partial writes after crash; manual file manipulation or bad restore.
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
- Data file partition position
- Error reading partition
- Error reading partition
- Failed to advance to the next index position. Index is…
- Failed to go to the next entry in index
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/88c6531ec1c3e57b.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/io/sstable/format/bti/BtiTableScrubber.java:185
String keyName = key == null ? "(unreadable key)" : keyString(key);
outputHandler.debug("partition %s is %s", keyName, FBUtilities.prettyPrintMemory(dataSizeFromIndex));
try
{
if (key == null)
throw new IOError(new IOException("Unable to read partition key from data file", keyReadError));
if (currentIndexKey != null && !key.getKey().equals(currentIndexKey))
{
throw new IOError(new IOException(String.format("Key from data file (%s) does not match key from index file (%s)",
ByteBufferUtil.bytesToHex(key.getKey()), ByteBufferUtil.bytesToHex(currentIndexKey))));
}
if (indexIterator != null && dataSizeFromIndex > dataFile.length())
throw new IOError(new IOException("Impossible partition size (greater than file length): " + dataSizeFromIndex));
if (indexIterator != null && dataStart != dataStartFromIndex)
outputHandler.warn("Data file partition position %d differs from index file row position %d", dataStart, dataStartFromIndex);
if (tryAppend(prevKey, key, writer))
prevKey = key;
}
catch (Throwable th)
{
throwIfFatal(th);
outputHandler.warn(th, "Error reading partition %s (stacktrace follows):", keyName);
if (currentIndexKey != null
&& (key == null || !key.getKey().equals(currentIndexKey) || dataStart != dataStartFromIndex))
{
// position where the row should start in a data file (right after the partition key)
long rowStartFromIndex = dataStartFromIndex + TypeSizes.SHORT_SIZE + currentIndexKey.remaining();
outputHandler.output("Retrying from partition index; data is %s bytes starting at %s",
dataSizeFromIndex, rowStartFromIndex);
key = sstable.decorateKey(currentIndexKey);View on GitHub (pinned to 88fd0f6a0e)