{"record":{"id":"7acc1c4ba073131e","repo":"elastic/elasticsearch","slug":"malformed-input-at","errorCode":null,"errorMessage":"Malformed input at {}","messagePattern":"Malformed input at (.+?)","errorType":"exception","errorClass":"LZ4Exception","httpStatus":null,"severity":"error","filePath":"libs/lz4/src/main/java/org/elasticsearch/lz4/ESLZ4Decompressor.java","lineNumber":63,"sourceCode":"\n    private ESLZ4Decompressor() {}\n\n    @Override\n    public int decompress(byte[] src, final int srcOff, byte[] dest, final int destOff, int destLen) {\n\n        final int srcEnd = src.length;\n\n        return decompress(src, srcOff, srcEnd - srcOff, dest, destOff, destLen);\n    }\n\n    private int decompress(byte[] src, final int srcOff, final int srcLen, byte[] dest, final int destOff, int destLen) {\n        SafeUtils.checkRange(src, srcOff, srcLen);\n        SafeUtils.checkRange(dest, destOff, destLen);\n\n        if (destLen == 0) {\n            // Allow `srcLen > 1` despite just one byte being consumed since this 'fast' decompressor does not have to fully consume the src\n            if (srcLen < 1 || SafeUtils.readByte(src, srcOff) != 0) {\n                throw new LZ4Exception(\"Malformed input at \" + srcOff);\n            }\n            return 1;\n        }\n\n        final int srcEnd = srcOff + srcLen;\n        final int destEnd = destOff + destLen;\n\n        int sOff = srcOff;\n        int dOff = destOff;\n\n        while (true) {\n            if (sOff >= srcEnd) {\n                throw new LZ4Exception(\"Malformed input at \" + sOff);\n            }\n            final int token = SafeUtils.readByte(src, sOff) & 0xFF;\n            ++sOff;\n\n            // literals","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/lz4/src/main/java/org/elasticsearch/lz4/ESLZ4Decompressor.java#L45-L81","documentation":"ESLZ4Decompressor's fast decompress path handles destLen==0 specially: it expects at least one source byte and that byte to be 0x00 (the LZ4 EOF marker for empty output). If srcLen is less than 1 or the first source byte is non-zero, the stream is considered malformed. This guards the zero-length output edge case before the main decode loop.","triggerScenarios":"Calling ESLZ4Decompressor.decompress (or INSTANCE.decompress) with destLen=0 but the source buffer is empty or its first byte is not the 0x00 end-of-block sentinel. Typically the result of truncating or corrupting an LZ4 frame.","commonSituations":"Truncated LZ4-compressed stored fields or translog entries in Elasticsearch. Passing a buffer produced by a different LZ4 variant/format. Off-by-one destLen miscalculation that yields 0 when the source is actually a real block.","solutions":["Verify the source was produced by the matching LZ4 fast compressor (LZ4FastDecompressor's counterpart).","Ensure the compressed payload is not truncated; re-read or re-fetch the original bytes.","Check that destLen matches the originally compressed length; a 0 destLen with non-empty source indicates a length bookkeeping bug upstream."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Before decompressing, sanity-check the destLen==0 case\nif (destLen == 0 && (srcLen < 1 || src[srcOff] != 0)) {\n    throw new IllegalArgumentException(\"Invalid LZ4 empty-output block\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    int read = ESLZ4Decompressor.INSTANCE.decompress(src, srcOff, dest, destOff, destLen);\n} catch (LZ4Exception e) {\n    // input is corrupt/truncated; recover from replica or snapshot\n    throw new IllegalStateException(\"Corrupt LZ4 block at offset \" + srcOff, e);\n}","preventionTips":["Always pass the exact destLen used at compression time.","Verify source buffers are not truncated (check lengths against recorded frame sizes).","Wrap decompression in a try/catch for LZ4Exception and trigger recovery (replica/snapshot)."],"tags":["lz4","decompression","corruption","stored-fields","translog"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}