quarkusio/quarkus · error · IllegalArgumentException

Annotation does not have @Retention(RUNTIME):

Error message

Annotation does not have @Retention(RUNTIME): 

What it means

Arc's AnnotationLiteralProcessor generates annotation literal subclasses at build time. Jandex annotations must be marked runtime-visible (i.e. @Retention(RUNTIME)) for literal generation; otherwise an IllegalArgumentException is thrown naming the offending annotation instance.

Source

Thrown at independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/AnnotationLiteralProcessor.java:88

     * if not. Further, it is expected that the annotation type is available (that is,
     * {@code annotationClass != null}); an exception is thrown if not. Callers that expect
     * they always deal with runtime-retained annotations whose classes are available do not
     * have to check (and will get decent errors for free), but callers that can possibly deal
     * with class-retained annotations or missing annotation classes must check explicitly.
     * <p>
     * We call the generated implementation of the annotation type an <em>annotation literal class</em>
     * and the instance produced by the generated bytecode an <em>annotation literal instance</em>,
     * even though the generated code doesn't use CDI's {@code AnnotationLiteral}.
     *
     * @param bc will receive the bytecode sequence for instantiating the annotation literal class
     *        as a sequence of {@link BlockCreator} method calls
     * @param annotationClass the annotation type
     * @param annotationInstance the annotation instance; must match the {@code annotationClass}
     * @return an annotation literal instance result handle
     */
    public Expr create(BlockCreator bc, ClassInfo annotationClass, AnnotationInstance annotationInstance) {
        if (!annotationInstance.runtimeVisible()) {
            throw new IllegalArgumentException("Annotation does not have @Retention(RUNTIME): " + annotationInstance);
        }
        if (annotationClass == null) {
            throw new IllegalArgumentException("Annotation class not available: " + annotationInstance);
        }

        AnnotationLiteralClassInfo literal = cache.getValue(new CacheKey(annotationClass));

        ClassDesc generatedClass = ClassDesc.of(literal.generatedClassName);

        if (literal.annotationMembers().isEmpty()) {
            return bc.getStaticField(FieldDesc.of(generatedClass, "INSTANCE", generatedClass));
        }

        Expr[] ctorArgs = new Expr[literal.annotationMembers().size()];
        int argIndex = 0;
        for (MethodInfo annotationMember : literal.annotationMembers()) {
            AnnotationValue value = annotationInstance.value(annotationMember.name());
            if (value == null) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Declare the annotation with @Retention(RetentionPolicy.RUNTIME)
  2. Remove the non-runtime annotation from CDI-managed code
  3. Check that the Jandex index reflects the compiled annotation retention

Example fix

// before
@Target(TYPE) @Retention(RetentionPolicy.CLASS)
public @interface MyMarker {}
// after
@Target(TYPE) @Retention(RetentionPolicy.RUNTIME)
public @interface MyMarker {}
Defensive patterns

Strategy: validation

Validate before calling

Retention r = MyAnno.class.getAnnotation(Retention.class); if (r == null || r.value() != RetentionPolicy.RUNTIME) throw new IllegalArgumentException("needs RUNTIME");

Prevention

When it happens

Trigger: Arc.create(...) processing an annotation instance whose runtimeVisible() flag is false — typically a source/class-retention annotation — passed to AnnotationLiteralProcessor.create.

Common situations: Using an annotation declared with @Retention(SOURCE) or @Retention(CLASS) in CDI injection points; indexing code where retention metadata differs from expectations; custom annotations missing @Retention(RUNTIME).

Related errors


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