quarkusio/quarkus · error · ConfigurationException

The method `${method}` is using `@Keyed` but is not annotate

Error message

The method `${method}` is using `@Keyed` but is not annotated with `@Incoming`

What it means

In Reactive Messaging, @Keyed marks a parameter for keyed processing of a KeyedMulti stream, which only makes sense on an @Incoming consumer method. At build time, handleKeyedMulti rejects any method using @Keyed without @Incoming/@Incomings with a ConfigurationException.

Source

Thrown at extensions/smallrye-reactive-messaging/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/deployment/QuarkusMediatorConfigurationUtil.java:281

                configuration.setBlockingExecutionOrdered(false);
                configuration.setWorkerPoolName(QuarkusWorkerPoolRegistry.DEFAULT_VIRTUAL_THREAD_WORKER);
            } else {
                configuration.setBlockingExecutionOrdered(true);
            }
        }

        return configuration;
    }

    private static void handleKeyedMulti(MethodInfo methodInfo,
            RecorderContext recorderContext, QuarkusMediatorConfiguration configuration) {
        if (methodInfo.parametersCount() == 1) { // @Keyed can only be used with a single parameter, a keyed multi
            var info = methodInfo.parameters().get(0);
            var annotation = info.annotation(ReactiveMessagingDotNames.KEYED);
            if (annotation != null) {
                // Make sure we have a keyed multi and an incoming.
                if (methodInfo.annotation(INCOMING) == null && methodInfo.annotation(INCOMINGS) == null) {
                    throw new ConfigurationException(
                            "The method `" + methodInfo.name() + "` is using `@Keyed` but is not annotated with `@Incoming`");
                }
                if (info.type().kind() != Type.Kind.PARAMETERIZED_TYPE
                        || !info.type().asParameterizedType().name().equals(ReactiveMessagingDotNames.KEYED_MULTI)) {
                    throw new ConfigurationException("The method `" + methodInfo.name()
                            + "` is using `@Keyed` but the annotated parameter is not a `KeyedMulti`");
                }
                var extractor = (Class<? extends KeyValueExtractor>) recorderContext
                        .classProxy(annotation.value().asClass().name().toString());
                configuration.setKeyed(extractor);
            }
            if (info.type().kind() == Type.Kind.PARAMETERIZED_TYPE
                    && info.type().asParameterizedType().name().equals(ReactiveMessagingDotNames.KEYED_MULTI)) {
                var args = info.type().asParameterizedType().arguments();
                configuration.setKeyType(recorderContext.classProxy(args.get(0).name().toString()));
                configuration.setValueType(recorderContext.classProxy(args.get(1).name().toString()));
            }
        }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Add @Incoming("channel") to the method that uses @Keyed
  2. Remove @Keyed if the method is not a message consumer
  3. Verify the @Incoming import is io.smallrye.reactive.messaging.Incoming and the annotation was not accidentally removed

Example fix

// before
@Keyed String key, Multi<MyEvent> events
// after
@Incoming("events")
void process(@Keyed String key, KeyedMulti<String, MyEvent> events) { ... }
Defensive patterns

Strategy: validation

Validate before calling

if (method.getAnnotation(Keyed.class) != null
    && method.getAnnotation(Incoming.class) == null
    && method.getAnnotation(Incomings.class) == null) {
    throw new IllegalStateException("@Keyed requires @Incoming");
}

Prevention

When it happens

Trigger: Annotating a method parameter with @Keyed on a method that lacks @Incoming (e.g. an @Outgoing producer, a plain method, or a typo in the @Incoming annotation import).

Common situations: Copy-pasting @Keyed from a consumer to a producer; mixing io.smallrye.reactive.messaging.annotations.Incoming with a wrong import; refactoring that removed @Incoming while keeping @Keyed.

Related errors


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