{"record":{"id":"297152f2aa402654","repo":"quarkusio/quarkus","slug":"the-qualifier-aclass-was-used-repeatedly-but-it","errorCode":null,"errorMessage":"The qualifier ${aClass} was used repeatedly but it is not annotated with @java.lang.annotation.Repeatable","messagePattern":"The qualifier (.+?) was used repeatedly but it is not annotated with @java\\.lang\\.annotation\\.Repeatable","errorType":"exception","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/Qualifiers.java","lineNumber":79,"sourceCode":"            Map<Class<? extends Annotation>, Integer> timesQualifierWasSeen = new HashMap<>();\n            for (Annotation qualifier : qualifiers) {\n                verifyQualifier(qualifier.annotationType());\n                timesQualifierWasSeen.compute(qualifier.annotationType(), TimesSeenBiFunction.INSTANCE);\n            }\n            checkQualifiersForDuplicates(timesQualifierWasSeen);\n        }\n    }\n\n    // in various cases, specification requires to check qualifiers for duplicates and throw IAE\n    private static void checkQualifiersForDuplicates(Map<Class<? extends Annotation>, Integer> timesQualifierSeen) {\n        for (Entry<Class<? extends Annotation>, Integer> entry : timesQualifierSeen.entrySet()) {\n            checkQualifiersForDuplicates(entry.getKey(), entry.getValue());\n        }\n    }\n\n    private static void checkQualifiersForDuplicates(Class<? extends Annotation> aClass, Integer times) {\n        if (times > 1 && (aClass.getAnnotation(Repeatable.class) == null)) {\n            throw new IllegalArgumentException(\"The qualifier \" + aClass + \" was used repeatedly \" +\n                    \"but it is not annotated with @java.lang.annotation.Repeatable\");\n        }\n    }\n\n    boolean hasQualifiers(Set<Annotation> beanQualifiers, Annotation... requiredQualifiers) {\n        for (Annotation qualifier : requiredQualifiers) {\n            if (!hasQualifier(beanQualifiers, qualifier)) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    boolean hasQualifier(Iterable<Annotation> qualifiers, Annotation requiredQualifier) {\n\n        Class<? extends Annotation> requiredQualifierClass = requiredQualifier.annotationType();\n        Method[] members = requiredQualifierClass.getDeclaredMethods();\n","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/Qualifiers.java#L61-L97","documentation":"When building qualifier sets, Qualifiers counts how often each qualifier annotation appears. If the same qualifier class is supplied more than once and that annotation is not meta-annotated with @Repeatable, the combination is invalid per CDI semantics and IllegalArgumentException is thrown.","triggerScenarios":"Calling Arc.container().instance(Foo.class, new Literal(), new Literal()) or any select()/qualifier API passing the same non-repeatable qualifier annotation instance/class twice.","commonSituations":"Programmatic lookup code that accumulates qualifiers in a loop and appends duplicates; refactored code merging qualifier arrays; misunderstanding @Repeatable requirements when multiple identical qualifiers are meant to AND together.","solutions":["Pass each qualifier only once — duplicates are redundant since qualifiers match conjunctively.","If repetition is intentional, add @Repeatable to the qualifier annotation (with a container annotation) — though the CDI runtime here rejects duplicates regardless.","Deduplicate the qualifier array before calling select()/instance() (e.g. new LinkedHashSet<>(Arrays.asList(qualifiers))).","Use distinct qualifiers (e.g. @Named values) if you need multiple constraints."],"exampleFix":"// before\nInstance<Foo> i = Arc.container().select(Foo.class, new Qual1L(), new Qual1L());\n// after\nInstance<Foo> i = Arc.container().select(Foo.class, new Qual1L());","handlingStrategy":"validation","validationCode":"Set<Class<? extends Annotation>> seen = new LinkedHashSet<>();\nfor (Annotation q : qualifiers) {\n    if (!seen.add(q.annotationType())) {\n        throw new IllegalArgumentException(\"Duplicate qualifier \" + q.annotationType() + \" (not repeatable)\");\n    }\n}","typeGuard":"boolean allDistinct(Annotation... qs) {\n    return Arrays.stream(qs).map(Annotation::annotationType).distinct().count() == qs.length;\n}","tryCatchPattern":"try {\n    return Arc.container().select(type, qualifiers);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"not annotated with @java.lang.annotation.Repeatable\")) {\n        return Arc.container().select(type, Arrays.stream(qualifiers).distinct().toArray(Annotation[]::new));\n    }\n    throw e;\n}","preventionTips":["Deduplicate qualifier arrays before any CDI lookup","Never append the same qualifier twice when collecting constraints programmatically","Treat qualifiers as conjunctive: one instance per type is enough"],"tags":["cdi","qualifier","arc","validation"],"backgroundTag":"non-repeatable-qualifier-duplicate","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}