quarkusio/quarkus · error · java.lang.IllegalArgumentException

Annotation is not a registered qualifier: ${annotationType}

Error message

Annotation is not a registered qualifier: ${annotationType}

What it means

Qualifiers.verify() checks that every annotation passed to qualifier-matching APIs is one of the qualifiers registered in the container's deployment. If annotationType is not in allQualifiers, IllegalArgumentException is thrown. This catches lookups using annotations that were never declared as CDI qualifiers.

Source

Thrown at independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/Qualifiers.java:154

                return false;
            }
        }
        return true;
    }

    private static Object invoke(Method method, Object instance) {
        try {
            method.setAccessible(true);
            return method.invoke(instance);
        } catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(
                    "Error checking value of member method " + method.getName() + " on " + method.getDeclaringClass(), e);
        }
    }

    private void verifyQualifier(Class<? extends Annotation> annotationType) {
        if (!allQualifiers.contains(annotationType.getName())) {
            throw new IllegalArgumentException("Annotation is not a registered qualifier: " + annotationType);
        }
    }

    private static class TimesSeenBiFunction implements BiFunction<Class<? extends Annotation>, Integer, Integer> {

        private static final TimesSeenBiFunction INSTANCE = new TimesSeenBiFunction();

        private TimesSeenBiFunction() {
        }

        @Override
        public Integer apply(Class<? extends Annotation> k, Integer v) {
            return (v == null) ? 1 : (v + 1);
        }
    }
}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Add @jakarta.inject.Qualifier (with @Retention(RUNTIME)) to the annotation type and rebuild so it's indexed.
  2. Ensure the annotation's package is part of the indexed application/extension (Jandex index present).
  3. Check the annotation name — you may be using a similarly named non-qualifier annotation by mistake.
  4. After upgrading a library, verify the qualifier still exists and is registered; update the lookup accordingly.

Example fix

// before
@Retention(RUNTIME)
public @interface Cool { } // missing @Qualifier
// after
@Qualifier
@Retention(RUNTIME)
public @interface Cool { }
Defensive patterns

Strategy: validation

Validate before calling

static void requireQualifier(Class<? extends Annotation> a) {
    if (!a.isAnnotationPresent(jakarta.inject.Qualifier.class)) {
        throw new IllegalArgumentException(a + " is missing @Qualifier; it cannot be used in select()");
    }
}

Type guard

boolean isCdiQualifier(Class<? extends Annotation> a) {
    return a.isAnnotationPresent(jakarta.inject.Qualifier.class);
}

Try / catch

try {
    return Arc.container().instance(type, qualifier);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Annotation is not a registered qualifier")) {
        throw new IllegalStateException("Add @Qualifier to " + qualifier.annotationType() + " and rebuild", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Passing a plain (non-@Qualifier) annotation, or a qualifier from a library not part of the indexed deployment, into Arc.container().instance()/select() or Instance.select(...) as a qualifier argument.

Common situations: Typos or a forgotten @Qualifier meta-annotation on a custom annotation; using an annotation from a module not indexed by Jandex; lookups written against a qualifier that was removed/renamed in an upgrade.

Related errors


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