apache/cassandra · critical · java.io.IOException

Decompressed lengths mismatch

Error message

Decompressed lengths mismatch

What it means

LZ4Compressor.uncompress(byte[], int, int, byte[], int) decompresses a chunk and verifies that LZ4 produced exactly the number of bytes recorded in the chunk's stored decompressed length. If the frame decoder wrote fewer or more bytes than the header claims, the data is corrupt or misaligned, and an IOException with this message is thrown rather than returning silently truncated/extended output.

Source

Thrown at src/java/org/apache/cassandra/io/compress/LZ4Compressor.java:163

        final int writtenLength;
        try
        {
            writtenLength = decompressor.decompress(input,
                                                    inputOffset + INTEGER_BYTES,
                                                    inputLength - INTEGER_BYTES,
                                                    output,
                                                    outputOffset,
                                                    decompressedLength);
        }
        catch (LZ4Exception e)
        {
            throw new IOException(e);
        }

        if (writtenLength != decompressedLength)
        {
            throw new IOException("Decompressed lengths mismatch");
        }

        return decompressedLength;
    }

    public void uncompress(ByteBuffer input, ByteBuffer output) throws IOException
    {
        final int decompressedLength = (input.get() & 0xFF)
                | ((input.get() & 0xFF) << 8)
                | ((input.get() & 0xFF) << 16)
                | ((input.get() & 0xFF) << 24);

        try
        {
            int compressedLength = input.remaining();
            decompressor.decompress(input, input.position(), input.remaining(), output, output.position(), decompressedLength);
            input.position(input.position() + compressedLength);
            output.position(output.position() + decompressedLength);

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Verify and repair the affected SSTables (`nodetool scrub`, `nodetool verify`); restore the chunk from a backup or replica.
  2. Rebuild the affected SSTables from other replicas by running a repair (`nodetool repair`).
  3. Confirm the data was written with the same LZ4 compressor configuration (framing/level) as is being used to read it.
Defensive patterns

Strategy: try-catch

Try / catch

try {
    compressor.uncompress(input, inputOffset, inputLen, output, outputOffset);
} catch (IOException e) {
    if (e.getMessage().contains("Decompressed lengths mismatch")) {
        logger.warn("Corrupt chunk detected; failing over to replica", e);
        // mark sstable suspect / retry from replica
    } else throw e;
}

Prevention

When it happens

Trigger: Calling LZ4Compressor.uncompress on a byte buffer whose stored decompressed length does not match what LZ4 actually produced — i.e. corrupt, truncated, or bit-rotted SSTable chunk data, or data written by a different/incompatible LZ4 framing.

Common situations: Reading an SSTable damaged by hardware failure or an interrupted write; restoring backups copied incorrectly; reading data written by a mismatched Cassandra/LZ4 version.

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


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/386c89fe6962070f. Report an issue: GitHub.