quarkusio/quarkus · error · IllegalArgumentException
Multiple beans match the type:
Error message
Multiple beans match the type:
What it means
SchedulerUtils.instantiateBeanOrClass() resolves a task/skip-predicate Class either as a CDI bean (via Arc.container().select) or, if no bean exists, by calling its no-arg constructor. When multiple CDI beans match the requested type with @Any qualifier, the resolution is ambiguous and this IllegalArgumentException is thrown (note: the companion IllegalStateException covers reflection failures).
Source
Thrown at extensions/scheduler/common/src/main/java/io/quarkus/scheduler/common/runtime/util/SchedulerUtils.java:119
if (!value.isEmpty() && isConfigValue(value)) {
value = resolvePropertyExpression(adjustExpressionSyntax(value));
}
return value;
}
public static boolean isConfigValue(String val) {
return isSimpleConfigValue(val) || isConfigExpression(val);
}
public static ZoneId parseCronTimeZone(Scheduled scheduled) {
String timeZone = lookUpPropertyValue(scheduled.timeZone());
return timeZone.equals(Scheduled.DEFAULT_TIMEZONE) ? null : ZoneId.of(timeZone);
}
public static <T> T instantiateBeanOrClass(Class<T> type) {
Instance<T> instance = Arc.container().select(type, Any.Literal.INSTANCE);
if (instance.isAmbiguous()) {
throw new IllegalArgumentException("Multiple beans match the type: " + type);
} else if (instance.isUnsatisfied()) {
try {
return type.getConstructor().newInstance();
} catch (Exception e) {
throw new IllegalStateException("Unable to instantiate the class: " + type);
}
} else {
return instance.get();
}
}
private static boolean isSimpleConfigValue(String val) {
val = val.trim();
return val.startsWith("{") && val.endsWith("}");
}
/**
* Converts "{property}" to "${property}" for backwards compatibilityView on GitHub (pinned to e1c734241f)
Solutions
- Disambiguate the container: mark one bean @Alternative with @Priority, or use @Named and select by qualifier
- Remove or deactivate the duplicate bean (e.g. mock only active in the test profile without also keeping the production bean)
- Make the duplicate non-bean (@Vetoed or remove @ApplicationScoped) so instantiation falls back to the constructor
- Change the scheduled configuration to reference a unique concrete class
Example fix
// before
class MyTask {...} and @Mock class MyTaskMock extends MyTask {...} // both beans
// after
@Mock @Alternative @Priority(1)
class MyTaskMock extends MyTask {...} // ambiguity resolved Defensive patterns
Strategy: validation
Validate before calling
Instance<T> check = Arc.container().select(type, Any.Literal.INSTANCE);
if (check.isAmbiguous()) {
throw new IllegalStateException("Multiple beans of " + type + " - add @Alternative/@Priority or @Vetoed");
} Type guard
boolean uniquelyResolvable(Class<?> type) {
Instance<?> i = Arc.container().select(type, Any.Literal.INSTANCE);
return !i.isAmbiguous();
} Try / catch
try {
task = SchedulerUtils.instantiateBeanOrClass(MyTask.class);
} catch (IllegalArgumentException e) {
LOG.error("Ambiguous CDI beans for {} - qualify or veto duplicates", type, e);
} Prevention
- Ensure exactly one bean per scheduled task/predicate type
- Mark test mocks @Alternative with @Priority so they replace, not duplicate
- Use @Vetoed on classes meant only for reflective instantiation
- Keep task classes concrete and unique; avoid duplicate implementations across packages
When it happens
Trigger: Passing a Class to setTask/setAsyncTask/setSkipPredicate (or calling instantiateBeanOrClass directly) where two or more beans of that type exist in the CDI container, e.g. a bean plus a @Mock bean in tests, or multiple implementations/specializations of the same interface type.
Common situations: Test profiles adding a @Mock/@Alternative duplicate of a scheduled task bean; two beans of the same class in different packages both eligible; forgetting @Alternative/@Priority on a test replacement; accidentally making an abstract task class a bean.
Related errors
- Quartz scheduler is either explicitly disabled through quark
- Failed to instantiate the client headers factory ${class}. M
- Unable to instantiate the class:
- More than one active bean found: " + list
- The @Blocking, @NonBlocking and @RunOnVirtualThread annotati
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/fd5cbf10174014ec.
Report an issue: GitHub.