apache/pulsar · error · PulsarClientException.InvalidConfigurationException
Can't use batch receive, if the queue size is 0
Error message
Can't use batch receive, if the queue size is 0
What it means
batchReceive() requires a non-zero receiver queue size because the batch receive fills a collection from the consumer's internal queue; with receiverQueueSize=0 there is nowhere to buffer messages, so the client rejects the call up front with InvalidConfigurationException.
Source
Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/ConsumerBase.java:1048
case Closed:
throw new PulsarClientException.AlreadyClosedException("Consumer already closed");
case Terminated:
throw new PulsarClientException.AlreadyClosedException("Topic was terminated");
case Failed:
case Uninitialized:
throw new PulsarClientException.NotConnectedException();
default:
break;
}
}
private void verifyBatchReceive() throws PulsarClientException {
if (listener != null) {
throw new PulsarClientException.InvalidConfigurationException(
"Cannot use receive() when a listener has been set");
}
if (getCurrentReceiverQueueSize() == 0) {
throw new PulsarClientException.InvalidConfigurationException(
"Can't use batch receive, if the queue size is 0");
}
}
protected static final class OpBatchReceive<T> {
final CompletableFuture<Messages<T>> future;
final long createdAt;
private OpBatchReceive(CompletableFuture<Messages<T>> future) {
this.future = future;
this.createdAt = System.nanoTime();
}
static <T> OpBatchReceive<T> of(CompletableFuture<Messages<T>> future) {
return new OpBatchReceive<>(future);
}
}View on GitHub (pinned to 820761864e)
Solutions
- Set receiverQueueSize to a positive value (default 1000) in the ConsumerBuilder.
- Use plain receive()/receiveAsync() instead of batchReceive() when the queue size must remain 0.
Example fix
// before Consumer<byte[]> c = client.newConsumer().receiverQueueSize(0).subscribe(); Messages<byte[]> msgs = c.batchReceive(); // after Consumer<byte[]> c = client.newConsumer().receiverQueueSize(100).subscribe(); Messages<byte[]> msgs = c.batchReceive();
Defensive patterns
Strategy: validation
Validate before calling
if (consumer.getQueueSize() == 0) { /* use receive() instead of batchReceive() */ } Try / catch
try {
Messages<byte[]> msgs = consumer.batchReceive();
} catch (PulsarClientException.InvalidConfigurationException e) {
// receiverQueueSize is 0: switch to receiveAsync()
} Prevention
- Never combine receiverQueueSize(0) with batchReceive APIs.
- Centralize consumer construction so queue-size and receive-mode stay consistent.
- Default to the standard receiverQueueSize (1000) unless you have a specific reason.
When it happens
Trigger: Calling batchReceive() or batchReceiveAsync() on a consumer whose getCurrentReceiverQueueSize() is 0 — typically after ConsumerBuilder.receiverQueueSize(0) (often combined with a Key_Shared/exclusive pattern or memory-constrained setups).
Common situations: Setting receiverQueueSize(0) to get strict per-message ordering or low-latency behavior, then later adding batchReceive for throughput; copying configs between consumers.
Related errors
- Cannot use receive() when a listener has been set
- Can't use receive with timeout, if the queue size is 0
- At least one of maxNumMessages, maxNumBytes, timeout must be
- Must set timeout unit for timeout.
- Broker doesn't allow forced deletion of namespaces
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/47eb23adc129d8ea.
Report an issue: GitHub.