apache/pulsar · error · IllegalArgumentException
numPartitionsLimit should be greater than or equal to 1
Error message
numPartitionsLimit should be greater than or equal to 1
What it means
PartialRoundRobinMessageRouterImpl limits the number of partitions a producer will send to (a partial round-robin over partitions). The constructor validates numPartitionsLimit and throws this IllegalArgumentException for values below 1.
Source
Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/customroute/PartialRoundRobinMessageRouterImpl.java:43
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.apache.pulsar.client.api.Message;
import org.apache.pulsar.client.api.MessageRouter;
import org.apache.pulsar.client.api.TopicMetadata;
public class PartialRoundRobinMessageRouterImpl implements MessageRouter {
private final int numPartitionsLimit;
private final List<Integer> partialList = new CopyOnWriteArrayList<>();
private static final AtomicIntegerFieldUpdater<PartialRoundRobinMessageRouterImpl> PARTITION_INDEX_UPDATER =
AtomicIntegerFieldUpdater.newUpdater(PartialRoundRobinMessageRouterImpl.class, "partitionIndex");
@SuppressWarnings("unused")
private volatile int partitionIndex = 0;
public PartialRoundRobinMessageRouterImpl(final int numPartitionsLimit) {
if (numPartitionsLimit < 1) {
throw new IllegalArgumentException("numPartitionsLimit should be greater than or equal to 1");
}
this.numPartitionsLimit = numPartitionsLimit;
}
/**
* Choose a partition based on the topic metadata.
* Key hash routing isn't supported.
*
* @param msg message
* @param metadata topic metadata
* @return the partition to route the message.
*/
public int choosePartition(Message<?> msg, TopicMetadata metadata) {
final List<Integer> newPartialList = new ArrayList<>(getOrCreatePartialList(metadata));
return newPartialList
.get(signSafeMod(PARTITION_INDEX_UPDATER.getAndIncrement(this), newPartialList.size()));
}
View on GitHub (pinned to 820761864e)
Solutions
- Pass a numPartitionsLimit of at least 1.
- Clamp the configured value: Math.max(1, configuredLimit) before constructing the router.
- If the limit comes from configuration, validate it at load time with a clear error message.
Example fix
// before
int limit = Integer.parseInt(props.getProperty("numPartitionsLimit", "0"));
MessageRouter router = new PartialRoundRobinMessageRouterImpl(limit);
// after
int limit = Math.max(1, Integer.parseInt(props.getProperty("numPartitionsLimit", "1")));
MessageRouter router = new PartialRoundRobinMessageRouterImpl(limit); Defensive patterns
Strategy: validation
Validate before calling
int limit = Integer.parseInt(props.getProperty("numPartitionsLimit", "1"));
if (limit < 1) throw new IllegalArgumentException("numPartitionsLimit must be >= 1, got " + limit); Type guard
boolean isValidPartitionLimit(int n) { return n >= 1; } Try / catch
try { router = new PartialRoundRobinMessageRouterImpl(limit); } catch (IllegalArgumentException e) { router = new PartialRoundRobinMessageRouterImpl(1); } Prevention
- Default the limit to >= 1 at config load time.
- Clamp user/config-provided values with Math.max(1, value).
- Never derive the limit from a possibly-zero partition count.
When it happens
Trigger: Calling new PartialRoundRobinMessageRouterImpl(0) or any negative limit, or producerBuilder.partialRoundRobin(...) style APIs (e.g. ProducerBuilder#messageRouter or usePartialRoundRobin) with a limit configured as 0 or negative.
Common situations: Config value read from properties/default 0 before validation; off-by-one in code computing the limit from a partition count that is 0; misuse of the router constructor directly in unit tests.
Understand the failure class
Background: "must be a positive integer", "cannot be empty", "invalid argument": how invalid-argument errors work across open-source libraries — this error's family across 33 libraries.
Related errors
- earlyTokenRefreshPercent must be greater than 0.
- EarlyTokenRefreshPercent must be greater than 0.
- earlyTokenRefreshPercent must be greater than 0, got: ${valu
- Failed to clone ProducerConfigurationData
- topicNames needs to be = 1
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/fe8a239d962bee82.
Report an issue: GitHub.