{"record":{"id":"13f5ceb760a76848","repo":"apache/cassandra","slug":"failed-to-seek-to-next-row-position-d","errorCode":null,"errorMessage":"Failed to seek to next row position %d","messagePattern":"Failed to seek to next row position (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/java/org/apache/cassandra/io/sstable/format/bti/BtiTableScrubber.java","lineNumber":270,"sourceCode":"    {\n        return indexIterator != null && !indexIterator.isExhausted();\n    }\n\n    private boolean seekToNextPartition()\n    {\n        while (indexAvailable())\n        {\n            long nextRowPositionFromIndex = indexIterator.dataPosition();\n\n            try\n            {\n                dataFile.seek(nextRowPositionFromIndex);\n                return true;\n            }\n            catch (Throwable th)\n            {\n                throwIfFatal(th);\n                outputHandler.warn(th, \"Failed to seek to next row position %d\", nextRowPositionFromIndex);\n                badPartitions++;\n            }\n\n            try\n            {\n                indexIterator.advance();\n            }\n            catch (Throwable th)\n            {\n                outputHandler.warn(th, \"Failed to go to the next entry in index\");\n                throw Throwables.cleaned(th);\n            }\n        }\n\n        return false;\n    }\n\n    @Override","sourceCodeStart":252,"sourceCodeEnd":288,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/io/sstable/format/bti/BtiTableScrubber.java#L252-L288","documentation":"In seekToNextPartition, the BTI scrubber seeks the data file to the next index-reported position after a bad partition. If the seek itself throws (I/O error, invalid position beyond file bounds), this warning is logged, badPartitions is incremented, and the scrubber tries to advance the index iterator instead; if that also fails the scrub ends.","triggerScenarios":"`nodetool scrub` recovering from a bad partition where dataFile.seek(nextRowPositionFromIndex) fails — e.g. the index points beyond the end of a truncated Data.db or the file descriptor is in an error state.","commonSituations":"Truncated Data.db smaller than the offsets recorded in the index; failing storage returning I/O errors on seek; severe corruption where index offsets are nonsense.","solutions":["Let the scrub terminate gracefully; it reports unrecoverable state rather than crashing.","Compact or rewrite the table after scrub so index and data are regenerated consistently.","Restore Data.db/Index.db from a snapshot and run `nodetool repair`.","Validate file sizes: compare Data.db length against expected sstable size; a truncated file means restore, not scrub."],"exampleFix":"// Detect truncation before scrubbing:\n// before: scrub warns 'Failed to seek to next row position <n>' (offset past EOF)\n// after: check sizes then restore\n$ ls -l <data_dir>/*/*-Data.db\n$ sstablemetadata <path-to-Data.db>  # confirm metadata vs actual size","handlingStrategy":"validation","validationCode":"// Detect truncated Data.db before scrubbing\nlong actualSize = Files.size(Paths.get(dataDbPath));\nSSTableMetadataReader meta = sstablemetadata(dataDbPath);\n// if actualSize is far below the recorded uncompressed/uncompressed file expectations, restore instead of scrub","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Compare sstable file sizes against sstablemetadata output after any abnormal shutdown.","Restore from snapshots when Data.db is truncated; scrub cannot fix missing bytes.","Enable disk-level monitoring to catch I/O error bursts early.","Gracefully drain nodes before maintenance reboots."],"tags":["cassandra","scrub","sstable","io-error"],"backgroundTag":"file-read-failed","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"}