quarkusio/quarkus · error · IllegalArgumentException

the expansion factory must be positive

Error message

the expansion factory must be positive

What it means

BfReserveArgs.expansion(int) sets the EXPANSION option for the BF.RESERVE command when creating a scalable RedisBloom filter. The expansion factor must be strictly positive, so zero or negative values throw this IllegalArgumentException before any command reaches Redis.

Source

Thrown at extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/bloom/BfReserveArgs.java:37

     */
    public BfReserveArgs nonScaling() {
        this.nonScaling = true;
        return this;
    }

    /**
     * Set the expansion factory.
     * When capacity is reached, an additional sub-filter is created. The size of the new sub-filter is the size of
     * the last sub-filter multiplied by expansion. If the number of elements to be stored in the filter is unknown,
     * we recommend that you use an expansion of 2 or more to reduce the number of sub-filters. Otherwise, we recommend
     * that you use an expansion of 1 to reduce memory consumption. The default expansion value is 2.
     *
     * @param expansion the expansion factor, must be positive
     * @return the current {@link BfReserveArgs}
     */
    public BfReserveArgs expansion(int expansion) {
        if (expansion <= 0) {
            throw new IllegalArgumentException("the expansion factory must be positive");
        }
        this.expansion = expansion;
        return this;
    }

    @Override
    public List<Object> toArgs() {
        List<Object> list = new ArrayList<>();
        if (expansion > 0) {
            list.add("EXPANSION");
            list.add(Integer.toString(expansion));
        }
        if (nonScaling) {
            list.add("NONSCALING");
        }
        return list;
    }
}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Pass a positive factor, e.g. expansion(2).
  2. If the filter should not scale, use the NONSCALING variant instead of expansion(0).
  3. Default the configured value: value <= 0 ? 2 : value.

Example fix

// before
BfReserveArgs args = BfReserveArgs.reserver(0.01).expansion(cfg.expansion()); // 0 -> throws
// after
BfReserveArgs args = BfReserveArgs.reserver(0.01).expansion(Math.max(1, cfg.expansion()));
Defensive patterns

Strategy: validation

Validate before calling

int expansion = cfg.expansion();
if (expansion <= 0) {
    throw new IllegalArgumentException("BF.RESERVE expansion must be positive, got " + expansion);
}
BfReserveArgs.args().expansion(expansion);

Try / catch

try { reserveArgs.expansion(f); } catch (IllegalArgumentException e) { if (e.getMessage().contains("expansion")) { reserveArgs.expansion(2); } else { throw e; } }

Prevention

When it happens

Trigger: Calling BfReserveArgs.reserver(...).expansion(0) or a negative value — typically a zero-valued default from config or an uninitialized int field passed straight through.

Common situations: Creating filters from application configuration where the expansion property is missing and defaults to 0; computing the factor dynamically and getting <= 0; confusion with the NONSCALING option where expansion is irrelevant and left at 0.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/50bfa6119ec67e52. Report an issue: GitHub.