{"id":"fb61f37448c97bd0","repo":"apache/kafka","slug":"block-size-value-must-be-between-4-and-7","errorCode":null,"errorMessage":"Block size value must be between 4 and 7","messagePattern":"Block size value must be between 4 and 7","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/compress/Lz4BlockOutputStream.java","lineNumber":372,"sourceCode":"            this.blockSizeValue = blockSizeValue;\n            this.reserved3 = reserved3;\n            validate();\n        }\n\n        public static BD fromByte(byte bd) {\n            int reserved2 = (bd >>> 0) & 15;\n            int blockMaximumSize = (bd >>> 4) & 7;\n            int reserved3 = (bd >>> 7) & 1;\n\n            return new BD(reserved2, blockMaximumSize, reserved3);\n        }\n\n        private void validate() {\n            if (reserved2 != 0) {\n                throw new RuntimeException(\"Reserved2 field must be 0\");\n            }\n            if (blockSizeValue < 4 || blockSizeValue > 7) {\n                throw new RuntimeException(\"Block size value must be between 4 and 7\");\n            }\n            if (reserved3 != 0) {\n                throw new RuntimeException(\"Reserved3 field must be 0\");\n            }\n        }\n\n        // 2^(2n+8)\n        public int getBlockMaximumSize() {\n            return 1 << ((2 * blockSizeValue) + 8);\n        }\n\n        public byte toByte() {\n            return (byte) (((reserved2 & 15) << 0) | ((blockSizeValue & 7) << 4) | ((reserved3 & 1) << 7));\n        }\n    }\n\n}\n","sourceCodeStart":354,"sourceCodeEnd":390,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/compress/Lz4BlockOutputStream.java#L354-L390","documentation":"Thrown by BD.validate() inside Lz4BlockOutputStream when parsing or constructing an LZ4 frame Block Descriptor (BD) byte whose block-size bits encode a value outside the legal 4-7 range. Per the LZ4 frame spec (v1.5.1) only block sizes 64KB(4), 256KB(5), 1MB(6), 4MB(7) are permitted; the size is computed as 2^(2*n+8). It is a plain RuntimeException (unchecked), raised during decompression when BD.fromByte() decodes a non-conformant header, or when a caller manually constructs BD with an invalid code.","triggerScenarios":"Decompressing an LZ4-compressed Kafka record batch whose frame BD byte is corrupt/truncated (e.g. via Lz4BlockInputStream reading damaged bytes from a Kafka partition, a tampered message, or a partial fetch response). Also triggered if application code directly calls new Lz4BlockOutputStream.BD(n) with n outside [4,7]. On the write path Kafka always uses BLOCKSIZE_64KB (4), so a non-4 value here almost always indicates bit-rot on the read path.","commonSituations":"See trigger scenarios.","solutions":["Inspect the full stack trace: a decompression path (FetchResponse/RecordsIterator) points to corrupt or truncated data from a specific topic-partition; verify that broker and re-fetch that batch/segment.","Check producer side: ensure records were written by a Kafka client using LZ4 (standard Kafka LZ4 frame), not a raw lz4-java frame stream, and that producer and client library versions agree.","If reproducing locally, validate the offending byte sequence against the LZ4 frame format spec; confirm the BD byte's bits 4-6 decode to 4-7.","If constructing BD directly in code, pass only BLOCKSIZE_64KB (4) or another value in [4,7]."],"exampleFix":"// before (custom/invalid code)\nnew Lz4BlockOutputStream.BD(3); // throws: 3 < 4\n\n// after\nnew Lz4BlockOutputStream.BD(Lz4BlockOutputStream.BLOCKSIZE_64KB); // legal: 4 -> 64KB","handlingStrategy":"try-catch","validationCode":"// Validate an LZ4 frame's BD (Block Descriptor) byte before decompression.\n// Layout (per Lz4BlockOutputStream.BD): bits 0-3 reserved2, bits 4-6 blockSizeValue, bit 7 reserved3.\nboolean isValidLz4Bd(byte bd) {\n    int reserved2 = bd & 0x0F;\n    int blockSizeValue = (bd >>> 4) & 0x07;\n    int reserved3 = (bd >>> 7) & 0x01;\n    return reserved2 == 0 && blockSizeValue >= 4 && blockSizeValue <= 7 && reserved3 == 0;\n}\n// Only meaningful if you have raw frame bytes; otherwise rely on try-catch below.","typeGuard":null,"tryCatchPattern":"// Thrown as RuntimeException from Lz4BlockInputStream when reading a corrupt/malformed LZ4 frame;\n// Compression.wrapForInput wraps it in KafkaException.\ntry {\n    try (InputStream in = compression.wrapForInput(buffer, messageVersion, bufferSupplier)) {\n        in.read(sink);\n    }\n} catch (org.apache.kafka.common.KafkaException ke) {\n    if (ke.getCause() != null && ke.getCause().getMessage().contains(\"Block size value\")) {\n        // corrupt producer payload / wire data — drop the record, do not retry the same bytes\n        log.warn(\"Malformed LZ4 frame rejected\", ke);\n    } else {\n        throw ke;\n    }\n}","preventionTips":["This error is raised on DECOMPRESSION of bytes received from the broker, so it signals corrupt input, not bad client config.","Do not retry the same byte buffer — the bytes are malformed; surface it to DLQ / skip / offset-advance logic.","If you produce with Kafka's built-in LZ4 compression, frames are always well-formed; seeing this means data was damaged in transit or forged.","Keep your kafka-clients version consistent between producer and consumer to avoid frame-format mismatches."],"tags":["compression","lz4","decompression","kafka-client","data-corruption"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}