{"record":{"id":"d6764baebef1f1e1","repo":"flowable/flowable-engine","slug":"endpoint-registry-endpointregistry-does-not-have-d6764b","errorCode":null,"errorMessage":"Endpoint registry <endpointRegistry> does not have listenerContainers field","messagePattern":"Endpoint registry <endpointRegistry> does not have listenerContainers field","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"modules/flowable-event-registry-spring/src/main/java/org/flowable/eventregistry/spring/kafka/KafkaChannelDefinitionProcessor.java","lineNumber":790,"sourceCode":"            try {\n                logger.debug(\"Destroying message listener {} for channel {} in tenant {}\", listenerContainer, channelModel.getKey(), tenantId);\n                ((DisposableBean) listenerContainer).destroy();\n            } catch (Exception e) {\n                throw new RuntimeException(\"Failed to destroy listener container\", e);\n            }\n        }\n\n        Field listenerContainersField = ReflectionUtils.findField(endpointRegistry.getClass(), \"listenerContainers\");\n        if (listenerContainersField != null) {\n            listenerContainersField.setAccessible(true);\n            @SuppressWarnings(\"unchecked\")\n            Map<String, MessageListenerContainer> listenerContainers = (Map<String, MessageListenerContainer>) ReflectionUtils\n                .getField(listenerContainersField, endpointRegistry);\n            if (listenerContainers != null) {\n                listenerContainers.remove(endpointId);\n            }\n        } else {\n            throw new IllegalStateException(\"Endpoint registry \" + endpointRegistry + \" does not have listenerContainers field\");\n        }\n        logger.info(\"Finished unregistering endpoint {}\", endpointId);\n    }\n\n    /**\n     * Register a new {@link KafkaListenerEndpoint} alongside the\n     * {@link KafkaListenerContainerFactory} to use to create the underlying container.\n     * <p>The {@code factory} may be {@code null} if the default factory has to be\n     * used for that endpoint.\n     */\n    protected void registerEndpoint(KafkaListenerEndpoint endpoint, KafkaListenerContainerFactory<?> factory) {\n        Assert.notNull(endpoint, \"Endpoint must not be null\");\n        Assert.hasText(endpoint.getId(), \"Endpoint id must be set\");\n\n        Assert.state(this.endpointRegistry != null, \"No KafkaListenerEndpointRegistry set\");\n        // We need to start the container immediately only if the endpoint registry is already running,\n        // otherwise we should not start it and leave it to the registry to start all the containers when it starts.\n        // We also need to start immediately if the application context has already been refreshed.","sourceCodeStart":772,"sourceCodeEnd":808,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-event-registry-spring/src/main/java/org/flowable/eventregistry/spring/kafka/KafkaChannelDefinitionProcessor.java#L772-L808","documentation":"The processor unregisters endpoints by reflectively removing entries from the endpoint registry's 'listenerContainers' field. If that field cannot be found on the given registry class (incompatible KafkaListenerEndpointRegistry implementation), an IllegalStateException with this message is thrown. This guards against Spring Kafka versions whose internal registry layout changed.","triggerScenarios":"Using a KafkaListenerEndpointRegistry subclass/replacement that no longer declares a 'listenerContainers' field when a channel is undeployed.","commonSituations":"Major spring-kafka upgrade that renamed/restructured the registry internals; custom EndpointRegistry implementation passed in.","solutions":["Use the standard org.springframework.kafka.config.KafkaListenerEndpointRegistry that has the listenerContainers field.","Align spring-kafka version with the version Flowable's event-registry-spring was built against (check flowable dependency management).","Pin/downgrade spring-kafka to a compatible version if you upgraded recently.","Override the unregister path or subclass KafkaChannelDefinitionProcessor to handle your registry implementation."],"exampleFix":"// before\n@Bean public MyCustomRegistry kafkaListenerEndpointRegistry() { ... }\n// after\n@Bean public KafkaListenerEndpointRegistry kafkaListenerEndpointRegistry() { return new KafkaListenerEndpointRegistry(); }","handlingStrategy":"fallback","validationCode":"Field f = ReflectionUtils.findField(registry.getClass(), \"listenerContainers\");\nif (f == null) throw new IllegalStateException(\"Incompatible KafkaListenerEndpointRegistry: \" + registry.getClass());","typeGuard":null,"tryCatchPattern":"try {\n    undeploy(channelKey);\n} catch (IllegalStateException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"does not have listenerContainers field\")) {\n        log.error(\"Replace registry with standard KafkaListenerEndpointRegistry\", e);\n    } else { throw e; }\n}","preventionTips":["Use the stock org.springframework.kafka.config.KafkaListenerEndpointRegistry","Avoid custom EndpointRegistry implementations","Check spring-kafka version compatibility before upgrades"],"tags":["kafka","reflection","spring-kafka-version","incompatible-api"],"backgroundTag":"incompatible-source-type","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}