apache/pulsar · error · IOException

(wraps DataFormatException from zlib inflate)

Error message

(wraps DataFormatException from zlib inflate)

What it means

CompressionCodecZLib.decode inflates a compressed payload with java.util.zip.Inflater. If the bytes are not valid zlib data (corrupt, truncated, or produced with a different algorithm), inflate() throws DataFormatException, which is wrapped in an IOException and rethrown.

Solutions

  1. Verify the message was actually produced with ZLIB compression and use the matching codec to decode
  2. Check disk/storage health for corruption of the underlying ledger data
  3. Reproduce the data from a healthy source or skip the corrupted entries
Defensive patterns

Strategy: try-catch

Validate before calling

if (compressed == null || compressed.readableBytes() < 2) {
    throw new IllegalArgumentException("payload too small to be zlib data");
}
int cmf = compressed.getByte(0) & 0xff;
if ((cmf & 0x0f) != 8) {
    throw new IllegalArgumentException("not a zlib (deflate) payload");
}

Try / catch

try {
    return codec.decode(compressed);
} catch (IOException e) {
    throw new IllegalStateException("Corrupt zlib payload", e);
}

Prevention

When it happens

Trigger: decode() called on a buffer whose zlib header/checksum is corrupt, a payload truncated mid-stream, or a message that was compressed with a codec other than ZLib but decoded as ZLib.

Common situations: Bookkeeper/ledger corruption, manual topic data edits, reading messages written by a producer with mismatched compression settings, network/disk truncation during replication.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/35befa1e42b3d249. Report an issue: GitHub.

Appendix: source

Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/compression/CompressionCodecZLib.java:122

        int offset;
        if (encoded.hasArray()) {
            array = encoded.array();
            offset = encoded.arrayOffset() + encoded.readerIndex();
        } else {
            array = new byte[len];
            encoded.getBytes(encoded.readerIndex(), array);
            offset = 0;
        }

        int resultLength;
        Inflater inflater = this.inflater.get();
        inflater.reset();
        inflater.setInput(array, offset, len);

        try {
            resultLength = inflater.inflate(uncompressed.array(), uncompressed.arrayOffset(), uncompressedLength);
        } catch (DataFormatException e) {
            throw new IOException(e);
        }

        checkArgument(resultLength == uncompressedLength);

        uncompressed.writerIndex(uncompressedLength);
        return uncompressed;
    }
}

View on GitHub (pinned to 820761864e)