apache/kafka · error · IllegalArgumentException

lz4 doesn't support given compression level: level

Error message

lz4 doesn't support given compression level: level

What it means

IllegalArgumentException thrown by Lz4Compression.Builder.level(int) when the requested LZ4 compression level falls outside the supported range. Kafka pins LZ4 levels to net.jpountz.lz4 constants: minLevel=1, maxLevel=17, defaultLevel=9. The check is `level < 1 || 17 < level`. It is a fail-fast guard at builder time, surfaced before any record is compressed, so it almost always indicates a bad configuration value rather than a runtime data problem.

Source

Thrown at clients/src/main/java/org/apache/kafka/common/compress/Lz4Compression.java:92

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Lz4Compression that = (Lz4Compression) o;
        return level == that.level;
    }

    @Override
    public int hashCode() {
        return Objects.hash(level);
    }

    public static class Builder implements Compression.Builder<Lz4Compression> {
        private int level = LZ4.defaultLevel();

        public Builder level(int level) {
            if (level < LZ4.minLevel() || LZ4.maxLevel() < level) {
                throw new IllegalArgumentException("lz4 doesn't support given compression level: " + level);
            }

            this.level = level;
            return this;
        }

        @Override
        public Lz4Compression build() {
            return new Lz4Compression(level);
        }
    }
}

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Set the LZ4 level to a value in [1,17]; the default is 9, and most workloads use 9 (fast) or 17 (HC, slower).
  2. If you do not need a specific level, omit the level() call entirely so the builder uses LZ4.defaultLevel() (9).
  3. If passing negative levels or levels > 17, switch the codec to zstd (which accepts -131072..22) instead of lz4.
  4. Re-check the property name for your client version (e.g. compression.lz4.level) and ensure no stray 'level' value is inherited from a zstd/snappy config block.

Example fix

// before
Compression compression = Compression.of().lz4().level(0).build(); // throws: 0 < 1

// after
Compression compression = Compression.of().lz4().level(9).build(); // valid; or omit .level() to use default 9
Defensive patterns

Strategy: validation

Validate before calling

// Validate the level against Kafka's own bounds BEFORE calling the builder.
import org.apache.kafka.common.record.internal.CompressionType;
int sanitizeLz4Level(int requested) {
    int lo = CompressionType.LZ4.minLevel();
    int hi = CompressionType.LZ4.maxLevel();
    if (requested < lo || requested > hi) {
        return CompressionType.LZ4.defaultLevel(); // or throw your own IllegalArgumentException
    }
    return requested;
}
Compression lz4 = new Lz4Compression.Builder().level(sanitizeLz4Level(userLevel)).build();

Try / catch

try {
    new Lz4Compression.Builder().level(userLevel).build();
} catch (IllegalArgumentException e) {
    // message starts with "lz4 doesn't support given compression level"
    log.warn("Invalid LZ4 level {}, falling back to default", userLevel);
    compression = Compression.lz4(); // default-level factory
}

Prevention

When it happens

Trigger: Calling Compression.of().lz4().level(n) or Compression.lz4().withLevel(n) (and indirectly setting producer config compression.lz4.level / the legacy "lz4.level" / a Compression instance with an out-of-range level) where n is <=0, >=18, or any value Kafka's Lz4Compression.Builder rejects in [1,17]. Also reached via reflection/custom wrappers that invoke Builder.level directly.

Common situations: See trigger scenarios.

Related errors


AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03). Data as JSON: /data/errors/71c1f1db3ef21c35.json. Report an issue: GitHub.