{"record":{"id":"c7d35435b46e70a7","repo":"quarkusio/quarkus","slug":"the-use-of-interfaces-as-the-generic-type-of-lists","errorCode":null,"errorMessage":"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() + '","messagePattern":"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\\(\\) \\+ '","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions/spring-boot-properties/deployment/src/main/java/io/quarkus/spring/boot/properties/deployment/YamlListObjectHandler.java","lineNumber":201,"sourceCode":"                    mc.public_();\n                    mc.body(b -> {\n                        LocalVar resultHandle = b.localVar(\"resultHandle\", b.new_(ConstructorDesc.of(HashMap.class)));\n                        for (Map.Entry<String, String> entry : fieldNameMap.entrySet().stream()\n                                .sorted(Map.Entry.comparingByKey()).toList()) {\n                            b.invokeVirtual(\n                                    MethodDesc.of(HashMap.class, \"put\", Object.class, Object.class, Object.class),\n                                    resultHandle, Const.of(entry.getKey()), Const.of(entry.getValue()));\n                        }\n                        b.return_(resultHandle);\n                    });\n                });\n            }\n        });\n    }\n\n    private void validateClass(ClassInfo classInfo, Member member) {\n        if (Modifier.isInterface(classInfo.flags())) {\n            throw new IllegalArgumentException(\n                    \"The use of interfaces as the generic type of Lists fields / methods is not allowed. Offending field is '\"\n                            + member.name() + \"' of class '\" + member.declaringClass().name().toString() + \"'\");\n        }\n        if (!classInfo.hasNoArgsConstructor()) {\n            throw new IllegalArgumentException(\n                    String.format(\"Class '%s' which is used as %s in class '%s' must have a no-args constructor\", classInfo,\n                            member.phraseUsage(), member.declaringClass().name().toString()));\n        }\n        if (!Modifier.isPublic(classInfo.flags())) {\n            throw new IllegalArgumentException(\n                    String.format(\"Class '%s' which is used as %s in class '%s' must be a public class\", classInfo,\n                            member.phraseUsage(), member.declaringClass().name().toString()));\n        }\n    }\n\n    private ClassInfo validateType(Type type) {\n        if (type.kind() != Type.Kind.PARAMETERIZED_TYPE) {\n            throw new IllegalArgumentException(ILLEGAL_ARGUMENT_MESSAGE);","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/spring-boot-properties/deployment/src/main/java/io/quarkus/spring/boot/properties/deployment/YamlListObjectHandler.java#L183-L219","documentation":"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.","triggerScenarios":"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.","commonSituations":"Modeling config lists against an abstraction (List<Handler> where Handler is an interface) carried over from Spring Boot style configuration.","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)"],"exampleFix":"// before\nList<Handler> handlers();\n// after\nList<DefaultHandler> handlers();","handlingStrategy":"type-guard","validationCode":"static <T> void checkListElementType(List<T> listField, Class<?> cfg) {\n    // element type must be a concrete class\n}","typeGuard":"boolean isConcreteListElement(Type t) {\n    return t instanceof Class<?> c && !c.isInterface() && !c.isAnnotation();\n}","tryCatchPattern":"catch (IllegalArgumentException e) { if (e.getMessage().contains(\"not allowed\")) { /* use concrete element class */ } throw e; }","preventionTips":["Use concrete classes as config list element types","Keep config binding types simple and concrete; expose interfaces only in service layer"],"tags":["quarkus","yaml","config","interface"],"backgroundTag":"config-list-element-interface","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"}