{"record":{"id":"88c6531ec1c3e57b","repo":"apache/cassandra","slug":"data-file-partition-position-d-differs-from-index-88c653","errorCode":null,"errorMessage":"Data file partition position %d differs from index file row position %d","messagePattern":"Data file partition position (.+?) differs from index file row position (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/java/org/apache/cassandra/io/sstable/format/bti/BtiTableScrubber.java","lineNumber":185,"sourceCode":"            String keyName = key == null ? \"(unreadable key)\" : keyString(key);\n            outputHandler.debug(\"partition %s is %s\", keyName, FBUtilities.prettyPrintMemory(dataSizeFromIndex));\n\n            try\n            {\n                if (key == null)\n                    throw new IOError(new IOException(\"Unable to read partition key from data file\", keyReadError));\n\n                if (currentIndexKey != null && !key.getKey().equals(currentIndexKey))\n                {\n                    throw new IOError(new IOException(String.format(\"Key from data file (%s) does not match key from index file (%s)\",\n                                                                    ByteBufferUtil.bytesToHex(key.getKey()), ByteBufferUtil.bytesToHex(currentIndexKey))));\n                }\n\n                if (indexIterator != null && dataSizeFromIndex > dataFile.length())\n                    throw new IOError(new IOException(\"Impossible partition size (greater than file length): \" + dataSizeFromIndex));\n\n                if (indexIterator != null && dataStart != dataStartFromIndex)\n                    outputHandler.warn(\"Data file partition position %d differs from index file row position %d\", dataStart, dataStartFromIndex);\n\n                if (tryAppend(prevKey, key, writer))\n                    prevKey = key;\n            }\n            catch (Throwable th)\n            {\n                throwIfFatal(th);\n                outputHandler.warn(th, \"Error reading partition %s (stacktrace follows):\", keyName);\n\n                if (currentIndexKey != null\n                    && (key == null || !key.getKey().equals(currentIndexKey) || dataStart != dataStartFromIndex))\n                {\n\n                    // position where the row should start in a data file (right after the partition key)\n                    long rowStartFromIndex = dataStartFromIndex + TypeSizes.SHORT_SIZE + currentIndexKey.remaining();\n                    outputHandler.output(\"Retrying from partition index; data is %s bytes starting at %s\",\n                                         dataSizeFromIndex, rowStartFromIndex);\n                    key = sstable.decorateKey(currentIndexKey);","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/io/sstable/format/bti/BtiTableScrubber.java#L167-L203","documentation":"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.","triggerScenarios":"`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.","commonSituations":"Sstable data and index files mixed from different compaction generations (files copied/replaced independently); partial writes after crash; manual file manipulation or bad restore.","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`."],"exampleFix":"// Preventive operational fix: keep data+index components together\n// before: rsync only *-Data.db between snapshot dirs\n// after: copy the whole sstable component set (Data.db, Index.db, etc.) from one snapshot","handlingStrategy":"validation","validationCode":"// Ensure data and index belong to the same sstable generation before restore\n$ ls data/ks/tbl-<uuid>/  # copy the FULL component set xx-* (Data.db, Index.db, Statistics.db, TOC.txt)\n# Never mix components from different generations (different numeric prefixes)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["cassandra","scrub","sstable","index-mismatch"],"backgroundTag":"checksum-mismatch","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}