{"record":{"id":"9fa40e66d306b59f","repo":"flowable/flowable-engine","slug":"topics-or-topicpartitions-must-be-provided-but-not","errorCode":null,"errorMessage":"Topics or topicPartitions must be provided but not both for <endpoint>","messagePattern":"Topics or topicPartitions must be provided but not both for <endpoint>","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"modules/flowable-event-registry-spring/src/main/java/org/flowable/eventregistry/spring/kafka/SimpleKafkaListenerEndpoint.java","lineNumber":173,"sourceCode":"    public void setSplitIterables(boolean splitIterables) {\n        this.splitIterables = splitIterables;\n    }\n\n    @Override\n    public String getMainListenerId() {\n        return mainListenerId;\n    }\n\n    public void setMainListenerId(String mainListenerId) {\n        this.mainListenerId = mainListenerId;\n    }\n\n    @Override\n    public void afterPropertiesSet() throws Exception {\n        boolean topicsEmpty = getTopics().isEmpty();\n        boolean topicPartitionsEmpty = ObjectUtils.isEmpty(getTopicPartitionsToAssign());\n        if (!topicsEmpty && !topicPartitionsEmpty) {\n            throw new IllegalStateException(\"Topics or topicPartitions must be provided but not both for \" + this);\n        }\n        if (this.topicPattern != null && (!topicsEmpty || !topicPartitionsEmpty)) {\n            throw new IllegalStateException(\"Only one of topics, topicPartitions or topicPattern must are allowed for \"\n                    + this);\n        }\n        if (this.topicPattern == null && topicsEmpty && topicPartitionsEmpty) {\n            throw new IllegalStateException(\"At least one of topics, topicPartitions or topicPattern must be provided \"\n                    + \"for \" + this);\n        }\n    }\n\n    @Override\n    public String toString() {\n        return getClass().getSimpleName() + \"[\" + this.id\n            + \"] topics=\" + this.topics\n            + \"' | topicPattern='\" + this.topicPattern + \"'\"\n            + \"' | topicPartitions='\" + this.topicPartitions + \"'\"\n            + \" | messageListener='\" + messageListener + \"'\";","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-event-registry-spring/src/main/java/org/flowable/eventregistry/spring/kafka/SimpleKafkaListenerEndpoint.java#L155-L191","documentation":"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.","triggerScenarios":"Setting both setTopics(...) (or a non-empty topics list) and setTopicPartitionsToAssign(...) on the same SimpleKafkaListenerEndpoint before registering it with a KafkaListenerContainerFactory.","commonSituations":"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.","solutions":["Remove the setTopics(...) call if you intend manual partition assignment via setTopicPartitionsToAssign(...)","Remove setTopicPartitionsToAssign(...) and rely on consumer-group subscription if you intend topic subscription","Log/dump the endpoint toString() in the message to see which values were set","Validate configuration before calling the container factory's createListenerContainer"],"exampleFix":"// before\nendpoint.setTopics(Collections.singletonList(\"my-topic\"));\nendpoint.setTopicPartitionsToAssign(Collections.singletonList(new TopicPartitionOffset(\"my-topic\", 0)));\n// after\nendpoint.setTopicPartitionsToAssign(Collections.singletonList(new TopicPartitionOffset(\"my-topic\", 0)));","handlingStrategy":"validation","validationCode":"if (endpoint.getTopics() != null && !endpoint.getTopics().isEmpty() && !ObjectUtils.isEmpty(endpoint.getTopicPartitionsToAssign())) {\n    throw new IllegalArgumentException(\"SimpleKafkaListenerEndpoint cannot have both topics and topicPartitions set\");\n}","typeGuard":"boolean hasExclusiveTopicConfig(SimpleKafkaListenerEndpoint e) {\n    return !e.getTopics().isEmpty() && !ObjectUtils.isEmpty(e.getTopicPartitionsToAssign());\n}","tryCatchPattern":"try {\n    endpoint.afterPropertiesSet();\n} catch (IllegalStateException ex) {\n    log.error(\"Invalid endpoint config: {}\", ex.getMessage());\n    throw new ConfigurationException(ex);\n}","preventionTips":["Choose one subscription style (topics, partitions, or pattern) per endpoint and document it","Build endpoints via a single factory/builder that enforces mutual exclusivity","Call afterPropertiesSet() in unit tests to validate endpoint config early"],"tags":["kafka","configuration","spring"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}