apache/pulsar · error · IllegalArgumentException

topicNames needs to be = 1

Error message

topicNames needs to be = 1

What it means

ReaderConfigurationData.getTopicName() returns the single topic a reader is bound to, and throws this IllegalArgumentException if topicNames contains more than one entry. Readers are single-topic constructs, so multi-topic configuration is invalid.

Source

Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/conf/ReaderConfigurationData.java:180

    private long autoUpdatePartitionsIntervalSeconds = 60;

    private transient List<ReaderInterceptor<T>> readerInterceptorList;

    // max pending chunked message to avoid sending incomplete message into the queue and memory
    private int maxPendingChunkedMessage = 10;

    private boolean autoAckOldestChunkedMessageOnQueueFull = false;

    private long expireTimeOfIncompleteChunkedMessageMillis = TimeUnit.MINUTES.toMillis(1);

    private SubscriptionMode subscriptionMode = SubscriptionMode.NonDurable;

    private SubscriptionInitialPosition subscriptionInitialPosition = SubscriptionInitialPosition.Latest;

    @JsonIgnore
    public String getTopicName() {
        if (topicNames.size() > 1) {
            throw new IllegalArgumentException("topicNames needs to be = 1");
        }
        return topicNames.iterator().next();
    }

    @JsonIgnore
    public void setTopicName(String topicNames) {
        //Compatible with a single topic
        this.topicNames.clear();
        this.topicNames.add(topicNames);
    }

    @SuppressWarnings("unchecked")
    public ReaderConfigurationData<T> clone() {
        try {
            ReaderConfigurationData<T> clone = (ReaderConfigurationData<T>) super.clone();
            clone.setTopicNames(new HashSet<>(clone.getTopicNames()));
            return clone;
        } catch (CloneNotSupportedException e) {

View on GitHub (pinned to 820761864e)

Solutions

  1. Ensure topicNames contains exactly one topic before creating a Reader.
  2. Use ConsumerBuilder with subscriptionType Exclusive/subscription name instead of a Reader when multiple topics are needed.
  3. Call getTopicNames() and validate size == 1 before calling getTopicName().
  4. If reusing shared config, build a fresh ReaderConfigurationData with a single topic.

Example fix

// before
ReaderConfigurationData<byte[]> conf = new ReaderConfigurationData<>();
conf.setTopicNames(Sets.newHashSet("t1", "t2"));
String topic = conf.getTopicName(); // throws
// after
conf.setTopicNames(Sets.newHashSet("t1"));
String topic = conf.getTopicName();
Defensive patterns

Strategy: validation

Validate before calling

if (readerConf.getTopicNames() == null || readerConf.getTopicNames().size() != 1) {
  throw new IllegalArgumentException("Reader requires exactly one topic, got: " + (readerConf.getTopicNames() == null ? 0 : readerConf.getTopicNames().size()));
}

Type guard

boolean isSingleTopic(ReaderConfigurationData<?> c) { return c.getTopicNames() != null && c.getTopicNames().size() == 1; }

Try / catch

try { String t = conf.getTopicName(); } catch (IllegalArgumentException e) { /* fall back to consumer-based multi-topic subscription */ }

Prevention

When it happens

Trigger: Setting more than one topic via ReaderBuilder.topics(...) or ReaderConfigurationData.setTopicNames(...) and then calling getTopicName() (directly or through ReaderImpl.createReaderAsync / the topic() accessor).

Common situations: Reusing a multi-topic consumer configuration object to create a reader; programmatically adding topics to a reader config; copying consumer topic lists into reader configs in test harnesses or migration code.

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


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/db920b7b7d3c288e. Report an issue: GitHub.