{"record":{"id":"034613e85cfb4259","repo":"apache/cassandra","slug":"invalid-negative-chunk-index-d-with-position-d","errorCode":null,"errorMessage":"Invalid negative chunk index %d with position %d","messagePattern":"Invalid negative chunk index (.+?) with position (.+?)","errorType":"exception","errorClass":"CorruptSSTableException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/io/compress/CompressionMetadata.java","lineNumber":338,"sourceCode":"        }\n    }\n\n    /**\n     * Get a chunk of compressed data (offset, length) corresponding to given position\n     *\n     * @param position Position in the file.\n     * @return pair of chunk offset and length.\n     */\n    public Chunk chunkFor(long position)\n    {\n        // position of the chunk\n        long idx = 8 * (position / parameters.chunkLength());\n\n        if (idx >= chunkOffsetsSize)\n            throw new CorruptSSTableException(new EOFException(), chunksIndexFile);\n\n        if (idx < 0)\n            throw new CorruptSSTableException(new IllegalArgumentException(String.format(\"Invalid negative chunk index %d with position %d\", idx, position)),\n                                              chunksIndexFile);\n\n        long chunkOffset = chunkOffsets.getLong(idx);\n        long nextChunkOffset = (idx + 8 == chunkOffsetsSize)\n                                ? compressedFileLength\n                                : chunkOffsets.getLong(idx + 8);\n\n        return new Chunk(chunkOffset, (int) (nextChunkOffset - chunkOffset - 4)); // \"4\" bytes reserved for checksum\n    }\n\n    public long getDataOffsetForChunkOffset(long chunkOffset)\n    {\n        long l = 0;\n        long h = (chunkOffsetsSize >> 3) - 1;\n        long idx, offset;\n\n        while (l <= h)\n        {","sourceCodeStart":320,"sourceCodeEnd":356,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/io/compress/CompressionMetadata.java#L320-L356","documentation":"chunkFor(position) computes a chunk index as 8 * (position / chunkLength) into the offset array. A negative index means the requested file position was negative, which is impossible for valid data; the writer treats it as corruption of the compressed file and throws CorruptSSTableException with the position and computed index. A too-large index similarly throws (idx >= chunkOffsetsSize).","triggerScenarios":"Calling chunkFor (directly or via chunk/upperChunkEnd/lowerChunkStart) with a negative position — typically from a corrupted truncated-file length, a bogus lastFlushOffset/bufferOffset, or a corrupt CompressionMetadata feeding invalid positions.","commonSituations":"Underlying data corruption producing negative file offsets; bugs or corruption in stored metadata (compressedFileLength/offsets) after a crash; passing a manually reconstructed position from a damaged file.","solutions":["Validate the file length and positions with sstablemetadata / sstable validate on the SSTable","Scrub or discard the corrupt SSTable and rebuild data via nodetool repair","Compare the compression index contents against the data file size on disk","If seen programmatically, assert position >= 0 before querying CompressionMetadata.chunkFor"],"exampleFix":"// before\nCompressionMetadata.Chunk c = metadata.chunkFor(suspectPosition); // throws if negative\n// after\nif (suspectPosition < 0 || suspectPosition >= metadata.compressedFileLength)\n    throw new IllegalArgumentException(\"position out of range: \" + suspectPosition);\nCompressionMetadata.Chunk c = metadata.chunkFor(suspectPosition);","handlingStrategy":"validation","validationCode":"// Java: range-check position before chunkFor\nstatic boolean isValidPosition(CompressionMetadata md, long pos) {\n    return pos >= 0 && pos < md.compressedFileLength;\n}","typeGuard":"static boolean safeChunkFor(CompressionMetadata md, long pos) {\n    return md != null && pos >= 0 && pos < md.compressedFileLength;\n}","tryCatchPattern":"try { return metadata.chunkFor(pos); }\ncatch (CorruptSSTableException e) { validateSSTable(path); throw e; }","preventionTips":["Never derive positions from unvalidated file data","Run sstable validate on suspect files before reads","Keep metadata and data files from the same generation together","Treat negative lengths/offsets in metadata as corruption immediately"],"tags":["sstable","compression","corruption","bounds"],"backgroundTag":"index-out-of-bounds","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}