quarkusio/quarkus · error · IllegalArgumentException
Not an annotation:
Error message
Not an annotation:
What it means
Annotations.annotationType() resolves the annotation interface (Class) for a given object (typically a AnnotationLiteral or annotation instance). It walks the class and its interfaces looking for one that isInterface() && isAnnotation(); if none is found it throws IllegalArgumentException. This guards APIs that require a real annotation instance.
Source
Thrown at independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Annotations.java:251
@SuppressWarnings("unchecked")
private static Class<? extends Annotation> annotationType(Annotation annotation) {
Class<? extends Annotation> annotationType = null;
Queue<Class<?>> candidates = new ArrayDeque<>();
candidates.add(annotation.getClass());
while (!candidates.isEmpty()) {
Class<?> candidate = candidates.remove();
if (candidate.isAnnotation()) {
annotationType = (Class<? extends Annotation>) candidate;
break;
}
Collections.addAll(candidates, candidate.getInterfaces());
}
if (annotationType == null) {
throw new IllegalArgumentException("Not an annotation: " + annotation);
}
return annotationType;
}
private static <A extends Annotation> org.jboss.jandex.AnnotationValue[] jandexAnnotationValues(
Class<A> annotationType, A annotationInstance) {
List<org.jboss.jandex.AnnotationValue> result = new ArrayList<>();
for (Method member : annotationType.getDeclaredMethods()) {
try {
// annotation types do not necessarily have to be public (if the annotation type
// and the build compatible extension class reside in the same package)
if (!member.canAccess(annotationInstance)) {
member.setAccessible(true);
}
result.add(jandexAnnotationValue(member.getName(), member.invoke(annotationInstance)));
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);View on GitHub (pinned to e1c734241f)
Solutions
- Pass a proper jakarta.enterprise.util.AnnotationLiteral subclass or a real annotation instance
- Verify the argument's class actually implements java.lang.annotation.Annotation at runtime
- Check that custom literal classes extend AnnotationLiteral<AnnotationType> with the correct type parameter
- If using proxies/bytecode enhancement, ensure the annotation interface is retained
Example fix
// before
Object q = new MyQualifierImpl(); // not an Annotation
// after
MyQualifier q = new MyQualifier() { /* AnnotationLiteral impl */ }; Defensive patterns
Strategy: type-guard
Validate before calling
if (!(candidate instanceof Annotation a)) throw new IllegalArgumentException("Not an annotation");
if (!a.annotationType().isAnnotation()) throw new IllegalArgumentException("No annotation interface"); Type guard
static boolean isAnnotationInstance(Object o) {
return o instanceof Annotation a && a.annotationType().isAnnotation();
} Try / catch
try { Class<? extends Annotation> t = Annotations.annotationType(ann); }
catch (IllegalArgumentException e) { log.error("Not an annotation: pass AnnotationLiteral subclass", e); } Prevention
- Always pass real annotations or AnnotationLiteral subclasses to Arc APIs
- Give custom literals the correct generic type parameter
- Unit-test literal classes by asserting annotationType() resolves
When it happens
Trigger: Calling an Arc API with an object that is not an annotation or annotation literal whose class hierarchy contains an annotation interface — e.g. passing a plain Object/subclass to a method expecting an annotation or AnnotationLiteral, or a literal class that fails to be recognized as implementing Annotation.
Common situations: Hand-rolled 'annotation literal' classes that extend the wrong base or are generated by bytecode manipulation; passing a qualifier instance of the wrong type; reflection-created proxies losing annotation marker interfaces.
Related errors
- Quarkus does not support CDI Full @Specializes annotation; t
- 'target' can only be a class, a field or a method: <target>
- IllegalStateException wrapping ClassNotFoundException for ge
- Unable to derive the logger name at ${injectionPoint}
- Improper integration of '${LogFilterFactory.class.getName()}
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/7911680c21ce91b8.
Report an issue: GitHub.