quarkusio/quarkus · error · IllegalArgumentException

Demand must be greater than zero

Error message

Demand must be greater than zero

What it means

RestMulti's Builder.withDemand(long) sets the request demand (backpressure batch size) forwarded to the underlying reactive stream. It throws IllegalArgumentException when demand <= 0, because reactive-streams demand must be a positive number.

Source

Thrown at independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/RestMulti.java:135

            }

            /**
             * Configure the {@code demand} signaled to the wrapped {@link Multi}, defaults to {@code 1}.
             *
             * <p>
             * A demand of {@code 1} guarantees serial/sequential processing, any higher demand supports
             * concurrent processing. A demand greater {@code 1}, with concurrent {@link Multi} processing,
             * does not guarantee element order - this means that elements emitted by the
             * {@link RestMulti#fromMultiData(Multi) RestMulti.fromMultiData(Multi)} source <code>Multi</code>}
             * will be produced in a non-deterministic order.
             *
             * @see MultiMerge#withConcurrency(int) Multi.createBy().merging().withConcurrency(int)
             * @see Multi#capDemandsTo(long)
             * @see Multi#capDemandsUsing(LongFunction)
             */
            public Builder<T> withDemand(long demand) {
                if (demand <= 0) {
                    throw new IllegalArgumentException("Demand must be greater than zero");
                }
                this.demand = demand;
                return this;
            }

            /**
             * Configure whether objects produced by the wrapped {@link Multi} are encoded as JSON array elements, which is the
             * default.
             *
             * <p>
             * {@code encodeAsJsonArray(false)} produces separate JSON objects.
             *
             * <p>
             * This property is only used for JSON object results and ignored for SSE and chunked streaming.
             */
            public Builder<T> encodeAsJsonArray(boolean encodeAsJsonArray) {
                this.encodeAsJsonArray = encodeAsJsonArray;
                return this;

View on GitHub (pinned to e1c734241f)

Solutions

  1. Pass a positive demand, e.g. `withDemand(256)`, or use the builder default by omitting the call.
  2. Validate/clamp configuration values before use: `long demand = Math.max(1, configuredDemand);`
  3. If demand comes from request parameters, validate > 0 and return 400 on invalid input.

Example fix

// before
long demand = config.batchSize(); // may be 0 when unset
return RestMulti.fromMulti(multi).withDemand(demand).build();
// after
long demand = config.batchSize() > 0 ? config.batchSize() : 256;
return RestMulti.fromMulti(multi).withDemand(demand).build();
Defensive patterns

Strategy: validation

Validate before calling

long demand = configuredDemand;
if (demand <= 0) {
    demand = DEFAULT_DEMAND; // e.g. 256
}

Type guard

boolean isPositiveDemand(Long d) {
    return d != null && d > 0;
}

Try / catch

try {
    return RestMulti.fromMulti(multi).withDemand(demand).build();
} catch (IllegalArgumentException e) {
    return RestMulti.fromMulti(multi).build(); // fall back to default demand
}

Prevention

When it happens

Trigger: Calling `RestMulti.fromMulti(aMulti).withDemand(n).build()` with n = 0, a negative value, or a value computed from config/headers that failed to parse to a positive number (e.g. Long.parseLong of an empty string would throw earlier, but a computed 0 reaches this check).

Common situations: Configuring demand via a property that defaults to 0 ('unset' sentinel); computing batch size from a page size or chunk config that evaluates to zero; unit tests passing 0 to check behavior.

Related errors


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