{"record":{"id":"9ef29e2231602023","repo":"flowable/flowable-engine","slug":"at-least-one-of-topics-topicpartitions-or-topicpa","errorCode":null,"errorMessage":"At least one of topics, topicPartitions or topicPattern must be provided for <endpoint>","messagePattern":"At least one of topics, topicPartitions or topicPattern must be provided 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":180,"sourceCode":"    }\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 + \"'\";\n    }\n}\n","sourceCodeStart":162,"sourceCodeEnd":194,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-event-registry-spring/src/main/java/org/flowable/eventregistry/spring/kafka/SimpleKafkaListenerEndpoint.java#L162-L194","documentation":"SimpleKafkaListenerEndpoint must have at least one subscription target before the listener container starts. If topicPattern is null and both the topics list and topicPartitions map are empty, afterPropertiesSet throws IllegalStateException because the endpoint would subscribe to nothing.","triggerScenarios":"Creating a SimpleKafkaListenerEndpoint, setting the message listener, but forgetting to set any of topics, topicPartitionsToAssign, or topicPattern before container registration.","commonSituations":"Dynamically built endpoints where topic values come from empty/missing configuration (e.g. empty environment variable, blank channel-model field); beans created but not yet configured at startup time.","solutions":["Call setTopics(...) with at least one topic name","Or call setTopicPattern(...) with a regex if dynamic matching is intended","Or call setTopicPartitionsToAssign(...) for manual partition assignment","Check upstream configuration source (channel model properties, env vars) for blank values"],"exampleFix":"// before\nSimpleKafkaListenerEndpoint endpoint = new SimpleKafkaListenerEndpoint();\nendpoint.setMessageListener(listener);\n// after\nSimpleKafkaListenerEndpoint endpoint = new SimpleKafkaListenerEndpoint();\nendpoint.setTopics(Collections.singletonList(\"my-topic\"));\nendpoint.setMessageListener(listener);","handlingStrategy":"validation","validationCode":"if (endpoint.getTopicPattern() == null && endpoint.getTopics().isEmpty() && ObjectUtils.isEmpty(endpoint.getTopicPartitionsToAssign())) {\n    throw new IllegalArgumentException(\"SimpleKafkaListenerEndpoint requires topics, topicPartitions, or a topicPattern\");\n}","typeGuard":"boolean hasNoSubscription(SimpleKafkaListenerEndpoint e) {\n    return e.getTopicPattern() == null && e.getTopics().isEmpty() && ObjectUtils.isEmpty(e.getTopicPartitionsToAssign());\n}","tryCatchPattern":"try {\n    endpoint.afterPropertiesSet();\n} catch (IllegalStateException ex) {\n    log.error(\"Endpoint has no subscription target: {}\", ex.getMessage());\n    throw ex;\n}","preventionTips":["Always set a subscription target immediately after constructing the endpoint","Fail fast when configuration values feeding topics are blank/empty","Cover endpoint construction in integration tests so missing topics surface at build time"],"tags":["kafka","configuration","spring"],"backgroundTag":"missing-required-config-field","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"}