apache/cassandra · error · org.apache.cassandra.transport.ProtocolException

Provided frame does not appear to be LZ4 compressed

Error message

Provided frame does not appear to be LZ4 compressed

What it means

LZ4-compressed native-protocol frames begin with a 4-byte big-endian uncompressed-length prefix followed by the LZ4 block. If the body is shorter than 4 bytes, the server cannot even read the prefix and throws this ProtocolException.

Solutions

  1. Fix the client LZ4 framing: prefix each compressed body with the 4-byte big-endian uncompressed length.
  2. Disable compression in client connection options to avoid LZ4 framing entirely.
  3. Verify no intermediary truncates or rewrites the frame body.
  4. Upgrade to an official driver that implements the LZ4 codec correctly.

Example fix

// before: raw LZ4 block without length header
body = lz4.block.compress(plain);
// after
byte[] compressed = lz4.block.compress(plain);
buf.writeInt(plain.length); // 4-byte uncompressed length prefix
buf.writeBytes(compressed);
Defensive patterns

Strategy: validation

Validate before calling

if (body.length < 4) throw new IllegalStateException("LZ4 frame requires a 4-byte uncompressed-length prefix");
int uncompressedLength = ((body[0]&0xFF)<<24)|((body[1]&0xFF)<<16)|((body[2]&0xFF)<<8)|(body[3]&0xFF);

Type guard

boolean hasLz4Header(byte[] body) { return body != null && body.length >= 4; }

Try / catch

try { ... } catch (ProtocolException e) {
    if (e.getMessage().contains("LZ4")) { // disable compression or add 4-byte length prefix
    }
}

Prevention

When it happens

Trigger: Client negotiates LZ4 compression but sends a body shorter than 4 bytes — empty body, plaintext body, or truncated frame.

Common situations: Client incorrectly enables lz4 without implementing the 4-byte length prefix; proxies/truncation; custom drivers writing raw LZ4 without the header.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/transport/Compressor.java:205

            catch (final Throwable e)
            {
                outputBuf.release();
                throw e;
            }
            finally
            {
                uncompressed.release();
            }
        }

        public Envelope decompress(Envelope compressed) throws IOException
        {
            try
            {
                byte[] input = CBUtil.readRawBytes(compressed.body);

                if (input.length < INTEGER_BYTES)
                    throw new ProtocolException("Provided frame does not appear to be LZ4 compressed");

                int uncompressedLength = ((input[0] & 0xFF) << 24)
                                       | ((input[1] & 0xFF) << 16)
                                       | ((input[2] & 0xFF) <<  8)
                                       | ((input[3] & 0xFF));

                validateUncompressedLength(uncompressedLength);
                ByteBuf output = CBUtil.allocator.heapBuffer(uncompressedLength);

                try
                {
                    int read = decompressor.decompress(input, INTEGER_BYTES, output.array(), output.arrayOffset(), uncompressedLength);
                    if (read != input.length - INTEGER_BYTES)
                        throw new IOException("Compressed lengths mismatch");

                    output.writerIndex(uncompressedLength);

                    return compressed.with(output);

View on GitHub (pinned to 88fd0f6a0e)