flowable/flowable-engine · error · IllegalStateException

Only one of topics, topicPartitions or topicPattern must are

Error message

Only one of topics, topicPartitions or topicPattern must are allowed for <endpoint>

What it means

A SimpleKafkaListenerEndpoint may specify exactly one subscription mode: explicit topics, explicit topicPartitions, or a topic regex pattern. This error is thrown when a topicPattern is set AND topics or topicPartitions are also set, which would make the subscription ambiguous.

Source

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

    @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 setTopics(...) and setTopicPartitionsToAssign(...) when using setTopicPattern(...)
  2. If concrete topics are needed, drop setTopicPattern(...) and list them in setTopics(...) only
  3. Ensure any shared base/builder object does not carry over a previously set topicPattern

Example fix

// before
endpoint.setTopicPattern(Pattern.compile("events\\..*"));
endpoint.setTopics(Collections.singletonList("events.main"));
// after
endpoint.setTopicPattern(Pattern.compile("events\\..*"));
Defensive patterns

Strategy: validation

Validate before calling

if (endpoint.getTopicPattern() != null && (!endpoint.getTopics().isEmpty() || !ObjectUtils.isEmpty(endpoint.getTopicPartitionsToAssign()))) {
    throw new IllegalArgumentException("topicPattern is mutually exclusive with topics and topicPartitions");
}

Type guard

boolean hasPatternConflict(SimpleKafkaListenerEndpoint e) {
    return e.getTopicPattern() != null && (!e.getTopics().isEmpty() || !ObjectUtils.isEmpty(e.getTopicPartitionsToAssign()));
}

Try / catch

try {
    endpoint.afterPropertiesSet();
} catch (IllegalStateException ex) {
    throw new IllegalArgumentException("Fix endpoint: " + ex.getMessage(), ex);
}

Prevention

When it happens

Trigger: Setting setTopicPattern(...) together with a non-empty setTopics(...) or setTopicPartitionsToAssign(...) on the same endpoint, validated in afterPropertiesSet.

Common situations: Template/base endpoint that already sets topicPattern getting topics added dynamically; annotation-derived config merged with programmatic pattern config; misunderstanding that pattern plus concrete topics is additive (it is not).

Related errors


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