quarkusio/quarkus · error · IllegalArgumentException

@ExactlyOnce on method ${methodName}: outgoing channel '${ou

Error message

@ExactlyOnce on method ${methodName}: outgoing channel '${outgoingChannel}' is not managed by the Kafka connector

What it means

Exactly-once processing requires the produced record to be sent within the same Kafka transaction as the offset commit, which is only possible when the outgoing channel uses the Kafka connector. This build-time error reports that the @Outgoing channel is not Kafka-connector-managed.

Source

Thrown at extensions/smallrye-reactive-messaging-kafka/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/kafka/deployment/SmallRyeReactiveMessagingKafkaProcessor.java:223

            boolean isSuspend = method.parameterTypes().stream()
                    .anyMatch(t -> t.name().equals(DotNames.CONTINUATION));
            if (isSuspend) {
                throw new IllegalArgumentException(
                        "@ExactlyOnce on method " + methodName
                                + " does not support Kotlin suspend functions");
            }

            String incomingChannel = incoming.value().asString();
            String outgoingChannel = outgoing.value().asString();

            if (!discoveryState.isKafkaConnector(channelsManagedByConnectors, true, incomingChannel)) {
                throw new IllegalArgumentException(
                        "@ExactlyOnce on method " + methodName
                                + ": incoming channel '" + incomingChannel + "' is not managed by the Kafka connector");
            }
            if (!discoveryState.isKafkaConnector(channelsManagedByConnectors, false, outgoingChannel)) {
                throw new IllegalArgumentException(
                        "@ExactlyOnce on method " + methodName
                                + ": outgoing channel '" + outgoingChannel + "' is not managed by the Kafka connector");
            }

            LOGGER.infof("Exactly-once processing detected on method %s#%s, " +
                    "configuring channels '%s' (incoming) and '%s' (outgoing)",
                    method.declaringClass().name(), method.name(), incomingChannel, outgoingChannel);

            // Auto-configure outgoing channel for transactions
            produceRuntimeConfigurationDefaultBuildItem(discoveryState, defaultConfigProducer,
                    getChannelOutgoingPropertyName(outgoingChannel, "transactional.id"),
                    "${quarkus.application.name}-" + outgoingChannel);
            produceRuntimeConfigurationDefaultBuildItem(discoveryState, defaultConfigProducer,
                    getChannelOutgoingPropertyName(outgoingChannel, "enable.idempotence"), "true");
            produceRuntimeConfigurationDefaultBuildItem(discoveryState, defaultConfigProducer,
                    getChannelOutgoingPropertyName(outgoingChannel, "acks"), "all");

            // Auto-configure incoming channel for exactly-once

View on GitHub (pinned to e1c734241f)

Solutions

  1. Set mp.messaging.outgoing.<channel>.connector=smallrye-kafka with proper topic/acks settings.
  2. Fix the channel name in @Outgoing to match the Kafka-configured channel.
  3. Remove @ExactlyOnce if the pipeline is not fully Kafka-based.

Example fix

// before
mp.messaging.outgoing.out.connector=smallrye-in-memory

// after
mp.messaging.outgoing.out.connector=smallrye-kafka
mp.messaging.outgoing.out.topic=out-topic
Defensive patterns

Strategy: validation

Validate before calling

String connector = config.getValue("mp.messaging.outgoing." + channel + ".connector", String.class);
if (!"smallrye-kafka".equals(connector)) {
    throw new IllegalStateException("outgoing channel must use smallrye-kafka for @ExactlyOnce");
}

Prevention

When it happens

Trigger: The @Outgoing channel name fails discoveryState.isKafkaConnector(channelsManagedByConnectors, false, channel) — e.g. configured for another connector or an in-memory emitter.

Common situations: Producing to an in-memory channel or AMQP/Pulsar outgoing channel while the incoming is Kafka, or a missing/incorrect connector property for the outgoing channel.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/f235cfac9a2ff81f. Report an issue: GitHub.