apache/pulsar · error · PulsarClientException.InvalidConfigurationException
Can't use receive with timeout, if the queue size is 0
Error message
Can't use receive with timeout, if the queue size is 0
What it means
A consumer created with receiverQueueSize=0 (typically for readers or exactly-once / seek-heavy patterns) has no internal buffer to hold a message for the timeout-based receive to poll from, so receive(int timeout, TimeUnit unit) rejects this configuration with InvalidConfigurationException. Queue-size-0 consumers only deliver via async/internal paths, so the timed synchronous receive is unsupported by design.
Source
Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/ConsumerBase.java:306
return FutureUtil.failedFuture(new PulsarClientException.InvalidConfigurationException(
"Cannot use receive() when a listener has been set"));
}
try {
verifyConsumerState();
} catch (PulsarClientException e) {
return FutureUtil.failedFuture(e);
}
return internalReceiveAsync();
}
protected abstract Message<T> internalReceive() throws PulsarClientException;
protected abstract CompletableFuture<Message<T>> internalReceiveAsync();
@Override
public Message<T> receive(int timeout, TimeUnit unit) throws PulsarClientException {
if (getCurrentReceiverQueueSize() == 0) {
throw new PulsarClientException.InvalidConfigurationException(
"Can't use receive with timeout, if the queue size is 0");
}
if (listener != null) {
throw new PulsarClientException.InvalidConfigurationException(
"Cannot use receive() when a listener has been set");
}
verifyConsumerState();
return internalReceive(timeout, unit);
}
protected abstract Message<T> internalReceive(long timeout, TimeUnit unit) throws PulsarClientException;
@Override
public Messages<T> batchReceive() throws PulsarClientException {
verifyBatchReceive();
verifyConsumerState();
return internalBatchReceive();View on GitHub (pinned to 820761864e)
Solutions
- Set receiverQueueSize to at least 1 in the ConsumerBuilder/ReaderBuilder
- Use receive() or receiveAsync() instead of the timed receive(timeout, unit)
- Use Reader.readNext(timeout, unit), which is designed for reader-style consumption
Example fix
// before
Reader<String> r = client.newReader(Schema.STRING)
.topic("t").readerName("rd")
.receiverQueueSize(0).create();
Message<String> m = consumer.receive(1, TimeUnit.SECONDS);
// after
Reader<String> r = client.newReader(Schema.STRING)
.topic("t").readerName("rd")
.receiverQueueSize(0).create();
Message<String> m = r.readNext(1, TimeUnit.SECONDS); Defensive patterns
Strategy: validation
Validate before calling
// check before using timed receive
// receiverQueueSize is fixed at build time; keep a flag from your builder
if (receiverQueueSize == 0) {
throw new IllegalStateException("Timed receive() unsupported with receiverQueueSize=0; use Reader.readNext");
} Type guard
boolean supportsTimedReceive(org.apache.pulsar.client.api.Consumer<T> c) {
return ((ConsumerBase<T>) c).getCurrentReceiverQueueSize() > 0;
} Try / catch
try {
Message<T> msg = consumer.receive(1, TimeUnit.SECONDS);
} catch (PulsarClientException.InvalidConfigurationException e) {
// queue size 0: switch to receive() / receiveAsync() / Reader.readNext
} Prevention
- Only set receiverQueueSize(0) on Reader/when you truly need no buffering
- Remember Readers must use readNext(), not consumer receive()
- Document receiverQueueSize choices in your consumer configuration layer
When it happens
Trigger: Building a consumer with ConsumerBuilder.receiverQueueSize(0) (or ConsumerConfigurationData with receiverQueueSize 0, common for Readers) and then calling consumer.receive(timeout, unit).
Common situations: Using a Reader with receiverQueueSize=0 for low-latency tailing and then calling the timed receive; tuning queue size to 0 to 'reduce latency' without realizing timed receive stops working; shared consumer builder where queue size 0 is set conditionally.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Cannot use receive() when a listener has been set
- Can't use batch receive, 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/f7667b7e6f14e92d.
Report an issue: GitHub.