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
- Add @Incoming("channel") to the method that uses @Keyed
- Remove @Keyed if the method is not a message consumer
- 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
- Only apply @Keyed to @Incoming consumer methods
- Check imports — use io.smallrye.reactive.messaging annotations consistently
- Run the build early; this is caught at augmentation time, not runtime
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
- The method `${method}` is using `@RunOnVirtualThread` but ex
- The method `${method}` is using `@Keyed` but the annotated p
- @ExactlyOnce on method ${methodName} must return a value to
- The @Blocking, @NonBlocking and @RunOnVirtualThread annotati
- Value not set for ${param}
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/1ff009d1880805bd.
Report an issue: GitHub.