apache/maven · error · IllegalArgumentException

Queue and batch sizes must be greater than 1

Error message

Queue and batch sizes must be greater than 1

What it means

SimplexTransferListener is the async transfer-event listener Maven wraps around progress displays (console download output). Its four-argument constructor validates queueSize and batchMaxSize: if either is < 1 it throws IllegalArgumentException 'Queue and batch sizes must be greater than 1'. (Wording is slightly off — the check actually rejects only values below 1, so exactly 1 is accepted.) The two-argument/convenience constructor uses defaults 1024/500; this error requires programmatic instantiation with bad values.

Source

Thrown at compat/maven-embedder/src/main/java/org/apache/maven/cli/transfer/SimplexTransferListener.java:74

     * Constructor that makes passed in delegate run on single thread, and will block on last event.
     */
    public SimplexTransferListener(TransferListener delegate) {
        this(delegate, QUEUE_SIZE, BATCH_MAX_SIZE, true);
    }

    /**
     * Constructor that may alter behaviour of this listener.
     *
     * @param delegate The delegate that should run on single thread.
     * @param queueSize The event queue size (default {@code 1024}).
     * @param batchMaxSize The maximum batch size delegate should receive (default {@code 500}).
     * @param blockOnLastEvent Should this listener block on last transfer end (completed or corrupted) block? (default {@code true}).
     */
    public SimplexTransferListener(
            TransferListener delegate, int queueSize, int batchMaxSize, boolean blockOnLastEvent) {
        this.delegate = requireNonNull(delegate);
        if (queueSize < 1 || batchMaxSize < 1) {
            throw new IllegalArgumentException("Queue and batch sizes must be greater than 1");
        }
        this.batchMaxSize = batchMaxSize;
        this.blockOnLastEvent = blockOnLastEvent;

        this.eventQueue = new ArrayBlockingQueue<>(queueSize);
        Thread updater = new Thread(this::feedConsumer);
        updater.setDaemon(true);
        updater.start();
    }

    public TransferListener getDelegate() {
        return delegate;
    }

    private void feedConsumer() {
        final ArrayList<Exchange> batch = new ArrayList<>(batchMaxSize);
        try {
            while (true) {

View on GitHub (pinned to e4093d4e12)

Solutions

  1. Pass values >= 1; keep the proven defaults queueSize=1024, batchMaxSize=500 unless you have measured a reason to change them.
  2. Clamp derived values: Math.max(1, computed) before calling the constructor.
  3. Validate external config at load time and reject missing/zero entries with a clear message instead of letting the constructor throw.
  4. For low-volume scenarios, remember batchMaxSize only caps batching — small values are legal and cheap; only < 1 is fatal.

Example fix

// before
int queue = config.getInt("transfer.queue", 0);
new SimplexTransferListener(delegate, queue, 0, true);

// after
int queue = Math.max(1, config.getInt("transfer.queue", 1024));
int batch = Math.max(1, config.getInt("transfer.batch", 500));
new SimplexTransferListener(delegate, queue, batch, true);
Defensive patterns

Strategy: validation

Validate before calling

// Guard before constructing the listener
if (queueSize < 1 || batchMaxSize < 1) {
    throw new IllegalArgumentException(
        "queueSize and batchMaxSize must be >= 1, got queue=" + queueSize + " batch=" + batchMaxSize);
}
return new SimplexTransferListener(delegate, queueSize, batchMaxSize, blockOnLastEvent);

Try / catch

try {
    return new SimplexTransferListener(delegate, queueSize, batchMaxSize, blockOnLastEvent);
} catch (IllegalArgumentException e) {
    if ("Queue and batch sizes must be greater than 1".equals(e.getMessage())) {
        // fall back to documented defaults rather than crashing the transfer UI
        return new SimplexTransferListener(delegate, 1024, 500, blockOnLastEvent);
    }
    throw e;
}

Prevention

When it happens

Trigger: Constructing new SimplexTransferListener(delegate, 0, 500, true), passing a batch size of 0, or computing sizes from configuration/capacity math that rounds down to zero (e.g. queue = total/branches with small inputs, or Integer.parseInt of an empty string defaulting via a ternary to 0).

Common situations: Custom Maven embedders or forks constructing the listener from externalized config where a missing key maps to 0. Test harnesses probing constructor validation. Refactors that changed a default from 1024 to a computed expression.

Related errors


AI-assisted analysis of apache/maven@e4093d4e12 (2026-08-21). Data as JSON: /api/errors/dbfe219c3c939295. Report an issue: GitHub.