flowable/flowable-engine · error · IllegalStateException

Topics or topicPartitions must be provided but not both for

Error message

Topics or topicPartitions must be provided but not both for <endpoint>

What it means

SimpleKafkaListenerEndpoint validates its topic configuration at container startup (afterPropertiesSet). Kafka listener endpoints can subscribe via topics list, explicit topicPartitions, or a topicPattern — but a topics list and explicit topicPartitions assignments are mutually exclusive. The endpoint is rejected with IllegalStateException when both are non-empty.

Source

Thrown at modules/flowable-event-registry-spring/src/main/java/org/flowable/eventregistry/spring/kafka/SimpleKafkaListenerEndpoint.java:173

    public void setSplitIterables(boolean splitIterables) {
        this.splitIterables = splitIterables;
    }

    @Override
    public String getMainListenerId() {
        return mainListenerId;
    }

    public void setMainListenerId(String mainListenerId) {
        this.mainListenerId = mainListenerId;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        boolean topicsEmpty = getTopics().isEmpty();
        boolean topicPartitionsEmpty = ObjectUtils.isEmpty(getTopicPartitionsToAssign());
        if (!topicsEmpty && !topicPartitionsEmpty) {
            throw new IllegalStateException("Topics or topicPartitions must be provided but not both for " + this);
        }
        if (this.topicPattern != null && (!topicsEmpty || !topicPartitionsEmpty)) {
            throw new IllegalStateException("Only one of topics, topicPartitions or topicPattern must are allowed for "
                    + this);
        }
        if (this.topicPattern == null && topicsEmpty && topicPartitionsEmpty) {
            throw new IllegalStateException("At least one of topics, topicPartitions or topicPattern must be provided "
                    + "for " + this);
        }
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + "[" + this.id
            + "] topics=" + this.topics
            + "' | topicPattern='" + this.topicPattern + "'"
            + "' | topicPartitions='" + this.topicPartitions + "'"
            + " | messageListener='" + messageListener + "'";

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Remove the setTopics(...) call if you intend manual partition assignment via setTopicPartitionsToAssign(...)
  2. Remove setTopicPartitionsToAssign(...) and rely on consumer-group subscription if you intend topic subscription
  3. Log/dump the endpoint toString() in the message to see which values were set
  4. Validate configuration before calling the container factory's createListenerContainer

Example fix

// before
endpoint.setTopics(Collections.singletonList("my-topic"));
endpoint.setTopicPartitionsToAssign(Collections.singletonList(new TopicPartitionOffset("my-topic", 0)));
// after
endpoint.setTopicPartitionsToAssign(Collections.singletonList(new TopicPartitionOffset("my-topic", 0)));
Defensive patterns

Strategy: validation

Validate before calling

if (endpoint.getTopics() != null && !endpoint.getTopics().isEmpty() && !ObjectUtils.isEmpty(endpoint.getTopicPartitionsToAssign())) {
    throw new IllegalArgumentException("SimpleKafkaListenerEndpoint cannot have both topics and topicPartitions set");
}

Type guard

boolean hasExclusiveTopicConfig(SimpleKafkaListenerEndpoint e) {
    return !e.getTopics().isEmpty() && !ObjectUtils.isEmpty(e.getTopicPartitionsToAssign());
}

Try / catch

try {
    endpoint.afterPropertiesSet();
} catch (IllegalStateException ex) {
    log.error("Invalid endpoint config: {}", ex.getMessage());
    throw new ConfigurationException(ex);
}

Prevention

When it happens

Trigger: Setting both setTopics(...) (or a non-empty topics list) and setTopicPartitionsToAssign(...) on the same SimpleKafkaListenerEndpoint before registering it with a KafkaListenerContainerFactory.

Common situations: Programmatically building endpoints where a default topics list is present and partition-assignment code also runs; copy-pasted endpoint setup; merging configuration from two sources that each set a different subscription style.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/9fa40e66d306b59f. Report an issue: GitHub.