quarkusio/quarkus · error · IllegalArgumentException
Interceptor binding was used repeatedly but is not @Repeata
Error message
Interceptor binding was used repeatedly but is not @Repeatable
What it means
ArC validates interceptor binding annotations passed to APIs like InterceptedCall/intercept(). If the same binding annotation type appears more than once and that annotation is not @Repeatable, the CDI spec requires IllegalArgumentException. Non-repeatable bindings can only appear once in a binding set.
Source
Thrown at independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/InterceptorBindings.java:51
verifyInterceptorBinding(interceptorBindings[0].annotationType());
} else {
Map<Class<? extends Annotation>, Integer> timesQualifierWasSeen = new HashMap<>();
for (Annotation interceptorBinding : interceptorBindings) {
verifyInterceptorBinding(interceptorBinding.annotationType());
timesQualifierWasSeen.compute(interceptorBinding.annotationType(), TimesSeenBiFunction.INSTANCE);
}
checkInterceptorBindingsForDuplicates(timesQualifierWasSeen);
}
}
// in various cases, specification requires to check interceptor bindings for duplicates and throw IAE
private static void checkInterceptorBindingsForDuplicates(Map<Class<? extends Annotation>, Integer> timesSeen) {
timesSeen.forEach(InterceptorBindings::checkInterceptorBindingsForDuplicates);
}
private static void checkInterceptorBindingsForDuplicates(Class<? extends Annotation> annClass, Integer timesSeen) {
if (timesSeen > 1 && !annClass.isAnnotationPresent(Repeatable.class)) {
throw new IllegalArgumentException("Interceptor binding " + annClass
+ " was used repeatedly but is not @Repeatable");
}
}
private void verifyInterceptorBinding(Class<? extends Annotation> annotationType) {
if (!allInterceptorBindings.contains(annotationType.getName())) {
throw new IllegalArgumentException("Annotation is not a registered interceptor binding: " + annotationType);
}
}
private static class TimesSeenBiFunction implements BiFunction<Class<? extends Annotation>, Integer, Integer> {
private static final TimesSeenBiFunction INSTANCE = new TimesSeenBiFunction();
@Override
public Integer apply(Class<? extends Annotation> k, Integer v) {
return v == null ? 1 : v + 1;
}
}View on GitHub (pinned to e1c734241f)
Solutions
- Remove the duplicate binding annotation from the call — one instance is enough
- Make the binding annotation @Repeatable with a proper container annotation if multiple occurrences are meaningful
- Merge the binding's members into a single annotation instance (e.g. one @Foo with multiple values) instead of repeating it
Example fix
// before
intercept(m, new Secured.Literal("read"), new Secured.Literal("write")); // @Secured not @Repeatable
// after
intercept(m, new Secured.Literal("read", "write")); // single instance, multiple values Defensive patterns
Strategy: validation
Validate before calling
static void requireNoDuplicateBindings(Annotation... bindings) {
Set<Class<? extends Annotation>> seen = new HashSet<>();
for (Annotation b : bindings) {
if (!seen.add(b.annotationType())
&& !b.annotationType().isAnnotationPresent(Repeatable.class)) {
throw new IllegalArgumentException(b.annotationType() + " used twice but is not @Repeatable");
}
}
} Try / catch
try {
intercept(method, bindings);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("used repeatedly but is not @Repeatable")) {
throw new IllegalStateException("Deduplicate bindings or make the annotation @Repeatable", e);
}
throw e;
} Prevention
- Before passing bindings, deduplicate by annotation type unless it's @Repeatable
- Prefer encoding multiple values in a single binding instance's members
- Document which custom bindings are repeatable to avoid misuse
When it happens
Trigger: Calling intercept(...) or other ArcContainer/Instance APIs with the same non-repeatable binding twice, e.g. intercept(myMethod, new Foo.Literal("a"), new Foo.Literal("b")) where @Foo is not @Repeatable.
Common situations: Assuming all interceptor bindings are repeatable like some built-in ones; copying a binding array that accidentally contains a duplicate; generated code emitting the binding twice.
Related errors
- Annotation is not a registered interceptor binding:
- Annotation does not have @Retention(RUNTIME):
- Array component kind is
- @BindingsSource may only define a class type, got ${kind}: $
- The @Blocking, @NonBlocking and @RunOnVirtualThread annotati
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/69f1b8961f15e743.
Report an issue: GitHub.