quarkusio/quarkus · error · IllegalArgumentException
The use of interfaces as the generic type of Lists fields /
Error message
The use of interfaces as the generic type of Lists fields / methods is not allowed. Offending field is ' + member.name() + ' of class ' + member.declaringClass().name().toString() + '
What it means
YamlListObjectHandler resolves the concrete element class of a List<...> field/method so it can instantiate elements when binding YAML config. Interfaces cannot be instantiated, so validation rejects them outright with IllegalArgumentException.
Source
Thrown at extensions/spring-boot-properties/deployment/src/main/java/io/quarkus/spring/boot/properties/deployment/YamlListObjectHandler.java:201
mc.public_();
mc.body(b -> {
LocalVar resultHandle = b.localVar("resultHandle", b.new_(ConstructorDesc.of(HashMap.class)));
for (Map.Entry<String, String> entry : fieldNameMap.entrySet().stream()
.sorted(Map.Entry.comparingByKey()).toList()) {
b.invokeVirtual(
MethodDesc.of(HashMap.class, "put", Object.class, Object.class, Object.class),
resultHandle, Const.of(entry.getKey()), Const.of(entry.getValue()));
}
b.return_(resultHandle);
});
});
}
});
}
private void validateClass(ClassInfo classInfo, Member member) {
if (Modifier.isInterface(classInfo.flags())) {
throw new IllegalArgumentException(
"The use of interfaces as the generic type of Lists fields / methods is not allowed. Offending field is '"
+ member.name() + "' of class '" + member.declaringClass().name().toString() + "'");
}
if (!classInfo.hasNoArgsConstructor()) {
throw new IllegalArgumentException(
String.format("Class '%s' which is used as %s in class '%s' must have a no-args constructor", classInfo,
member.phraseUsage(), member.declaringClass().name().toString()));
}
if (!Modifier.isPublic(classInfo.flags())) {
throw new IllegalArgumentException(
String.format("Class '%s' which is used as %s in class '%s' must be a public class", classInfo,
member.phraseUsage(), member.declaringClass().name().toString()));
}
}
private ClassInfo validateType(Type type) {
if (type.kind() != Type.Kind.PARAMETERIZED_TYPE) {
throw new IllegalArgumentException(ILLEGAL_ARGUMENT_MESSAGE);View on GitHub (pinned to e1c734241f)
Solutions
- Change the list element type from the interface to a concrete class with a public no-args constructor
- Introduce a concrete base/default implementation class and use List<Impl> in the config
- Move polymorphism out of the config binding (bind concrete class, expose interface separately)
Example fix
// before List<Handler> handlers(); // after List<DefaultHandler> handlers();
Defensive patterns
Strategy: type-guard
Validate before calling
static <T> void checkListElementType(List<T> listField, Class<?> cfg) {
// element type must be a concrete class
} Type guard
boolean isConcreteListElement(Type t) {
return t instanceof Class<?> c && !c.isInterface() && !c.isAnnotation();
} Try / catch
catch (IllegalArgumentException e) { if (e.getMessage().contains("not allowed")) { /* use concrete element class */ } throw e; } Prevention
- Use concrete classes as config list element types
- Keep config binding types simple and concrete; expose interfaces only in service layer
When it happens
Trigger: A @ConfigProperties class/interface (processed via quarkus-config-yaml list-of-object support) declares a field or method of type List<SomeInterface> where SomeInterface is an interface, not a class.
Common situations: Modeling config lists against an abstraction (List<Handler> where Handler is an interface) carried over from Spring Boot style configuration.
Related errors
- Support for List of objects in classes annotated with '@Conf
- Class '%s' which is used as %s in class '%s' must have a no-
- Class '%s' which is used as %s in class '%s' must be a publi
- YamlListObjectHandler can only be used for fields / methods
- The class (${name}) cannot be created during deployment.
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/c7d35435b46e70a7.
Report an issue: GitHub.