{"record":{"id":"a4de2fb05582b4cc","repo":"quarkusio/quarkus","slug":"exactlyonce-on-method-methodname-incoming-cha","errorCode":null,"errorMessage":"@ExactlyOnce on method ${methodName}: incoming channel '${incomingChannel}' is not managed by the Kafka connector","messagePattern":"@ExactlyOnce on method (.+?): incoming channel '(.+?)' is not managed by the Kafka connector","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions/smallrye-reactive-messaging-kafka/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/kafka/deployment/SmallRyeReactiveMessagingKafkaProcessor.java","lineNumber":218,"sourceCode":"            if (method.hasAnnotation(DotNames.TRANSACTIONAL) && method.hasAnnotation(DotNames.WITH_TRANSACTION)) {\n                throw new IllegalArgumentException(\n                        \"@ExactlyOnce on method \" + methodName\n                                + \" cannot combine @Transactional with @WithTransaction\");\n            }\n\n            boolean isSuspend = method.parameterTypes().stream()\n                    .anyMatch(t -> t.name().equals(DotNames.CONTINUATION));\n            if (isSuspend) {\n                throw new IllegalArgumentException(\n                        \"@ExactlyOnce on method \" + methodName\n                                + \" does not support Kotlin suspend functions\");\n            }\n\n            String incomingChannel = incoming.value().asString();\n            String outgoingChannel = outgoing.value().asString();\n\n            if (!discoveryState.isKafkaConnector(channelsManagedByConnectors, true, incomingChannel)) {\n                throw new IllegalArgumentException(\n                        \"@ExactlyOnce on method \" + methodName\n                                + \": incoming channel '\" + incomingChannel + \"' is not managed by the Kafka connector\");\n            }\n            if (!discoveryState.isKafkaConnector(channelsManagedByConnectors, false, outgoingChannel)) {\n                throw new IllegalArgumentException(\n                        \"@ExactlyOnce on method \" + methodName\n                                + \": outgoing channel '\" + outgoingChannel + \"' is not managed by the Kafka connector\");\n            }\n\n            LOGGER.infof(\"Exactly-once processing detected on method %s#%s, \" +\n                    \"configuring channels '%s' (incoming) and '%s' (outgoing)\",\n                    method.declaringClass().name(), method.name(), incomingChannel, outgoingChannel);\n\n            // Auto-configure outgoing channel for transactions\n            produceRuntimeConfigurationDefaultBuildItem(discoveryState, defaultConfigProducer,\n                    getChannelOutgoingPropertyName(outgoingChannel, \"transactional.id\"),\n                    \"${quarkus.application.name}-\" + outgoingChannel);\n            produceRuntimeConfigurationDefaultBuildItem(discoveryState, defaultConfigProducer,","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/smallrye-reactive-messaging-kafka/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/kafka/deployment/SmallRyeReactiveMessagingKafkaProcessor.java#L200-L236","documentation":"@ExactlyOnce requires both the incoming and outgoing channel to be Kafka-connector-managed, because exactly-once is implemented with Kafka consumer/producer transactions. This error reports that the incoming channel is served by a different connector (or in-memory/manual channels), so the extension cannot set up the transactional pipeline.","triggerScenarios":"The @Incoming channel name passed to discoveryState.isKafkaConnector(channelsManagedByConnectors, true, channel) is not registered as a Kafka connector channel at build time — e.g. it's an in-memory channel or another connector (Pulsar, AMQP).","commonSituations":"Typos in channel names, configuring the channel only via application.properties with a wrong connector type, or mixing an in-memory test channel with @ExactlyOnce.","solutions":["Set mp.messaging.incoming.<channel>.connector=smallrye-kafka (or remove an overriding connector value).","Correct the channel name in @Incoming so it matches the Kafka-configured channel.","Remove @ExactlyOnce if either channel is intentionally non-Kafka."],"exampleFix":"// before\nmp.messaging.incoming.in.connector=smallrye-amqp\n\n// after\nmp.messaging.incoming.in.connector=smallrye-kafka\nmp.messaging.incoming.in.topic=my-topic","handlingStrategy":"validation","validationCode":"// verify incoming channel connector before deploying\nString connector = config.getValue(\"mp.messaging.incoming.\" + channel + \".connector\", String.class);\nif (!\"smallrye-kafka\".equals(connector)) {\n    throw new IllegalStateException(\"incoming channel must use smallrye-kafka for @ExactlyOnce\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set mp.messaging.incoming.<ch>.connector=smallrye-kafka for exactly-once channels","Verify channel names match between annotations and properties","Run a build/test deploy before shipping; this fails fast at build time"],"tags":["kafka","reactive-messaging","configuration","exactly-once"],"backgroundTag":"channel-not-kafka-connector","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}