apache/kafka · error · IllegalArgumentException

zstd doesn't support given compression level: level

Error message

zstd doesn't support given compression level: level

What it means

IllegalArgumentException thrown by ZstdCompression.Builder.level(int) when the requested zstd compression level is outside the supported range. Kafka pins zstd levels to the zstd library constants: minLevel=-131072 (ZSTD_minCLevel), maxLevel=22 (ZSTD_MAX_CLEVEL), defaultLevel=3. The guard is `level < -131072 || 22 < level`. Like the LZ4 check it fires at builder time, before any bytes are compressed.

Source

Thrown at clients/src/main/java/org/apache/kafka/common/compress/ZstdCompression.java:129

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

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

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

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

            this.level = level;
            return this;
        }

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

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Set the zstd level to a value in [-131072, 22]; the default is 3, levels 1-19 are standard, 20-22 require --ultra and a lot of memory.
  2. If you do not need a specific level, omit .level() so the builder uses ZSTD.defaultLevel() (3).
  3. If you need extreme compression, use 19 (or 20-22 cautiously); do not exceed 22.
  4. Verify you are configuring the zstd codec and not accidentally applying an lz4/gzip level convention (which would under-use or over-shoot zstd's range).

Example fix

// before
Compression compression = Compression.of().zstd().level(23).build(); // throws: 23 > 22

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

Strategy: validation

Validate before calling

import org.apache.kafka.common.record.internal.CompressionType;
int sanitizeZstdLevel(int requested) {
    int lo = CompressionType.ZSTD.minLevel();
    int hi = CompressionType.ZSTD.maxLevel();
    if (requested < lo || requested > hi) {
        return CompressionType.ZSTD.defaultLevel();
    }
    return requested;
}
Compression zstd = new ZstdCompression.Builder().level(sanitizeZstdLevel(userLevel)).build();

Try / catch

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

Prevention

When it happens

Trigger: Calling Compression.of().zstd().level(n) (or setting producer config compression.zstd.level) with n > 22 or n < -131072. The upper bound (22) is by far the more common boundary to hit; the lower bound is effectively unreachable except by accident (e.g. a sign error or treating an unsigned config as signed).

Common situations: See trigger scenarios.

Related errors


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