apache/cassandra · critical · IOError
Key from data file (%s) does not match key from index file (
Error message
Key from data file (%s) does not match key from index file (%s)
What it means
Thrown during BTI sstable scrub when the partition key read from the data file does not match the key recorded in the index file for the same partition. This indicates index/data divergence — the data file content is not at the position the index expects, a strong sign of file corruption or interleaved/mismatched components.
Source
Thrown at src/java/org/apache/cassandra/io/sstable/format/bti/BtiTableScrubber.java:177
indexIterator = null;
currentIndexKey = null;
dataStartFromIndex = -1;
dataSizeFromIndex = -1;
}
}
}
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 != nullView on GitHub (pinned to 88fd0f6a0e)
Solutions
- Restore the complete, matching set of sstable components (Data.db, Index.db, etc.) from backup
- Drop the corrupt sstable and run repair to stream data from replicas
- Check that sstable files were not manually renamed — component generation must match the TOC
- Scrub with --no-validate to salvage what is readable, accepting some data loss
Defensive patterns
Strategy: try-catch
Validate before calling
// ensure index and data components belong to the same generation before scrub
if (!dataFile.getName().equals(indexFile.getName())) throw new IllegalStateException("component generation mismatch"); Try / catch
try { scrubInternal(...); } catch (IOError e) { logger.error("index/data key mismatch: restore matching components", e); } Prevention
- Never rename or hand-edit sstable component files
- Restore backups as complete sets
- Run repair to reconcile divergent replicas
- Snapshot before scrub
When it happens
Trigger: Scrubbing a BTI sstable where the data file was modified, truncated, or mixed with a different generation's index file; dataStart points to a different partition than currentIndexKey.
Common situations: Manually copied or renamed sstable components mixing generations, restore of partial backups, corruption from hardware failure, upgrades leaving mismatched components.
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
- Corrupt flags value for clustering prefix (isStatic flag set
- Corrupted sstable. Invalid flags found deserializing Deletio
- Failed to import sstable <filename>
- The requested position exceeds the index length
- Seeking to a partition at: ${position} did not land after an
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/6868f1defca7e2ed.
Report an issue: GitHub.