quarkusio/quarkus · error · IllegalArgumentException

Class '%s' which is used as %s in class '%s' must be a publi

Error message

Class '%s' which is used as %s in class '%s' must be a public class

What it means

Thrown by YamlListObjectHandler.validateClass when a class used as a nested Spring Boot properties type fails the public-visibility check. The handler supports deserializing spring-boot-properties YAML structures including generic list element types; the reflective/codegen binding path requires the element class (used as <member> in class <declaring class>) to be instantiable, so non-public classes (and interfaces and classes without no-arg constructors, checked by sibling guards) are rejected at build time.

Source

Thrown at extensions/spring-boot-properties/deployment/src/main/java/io/quarkus/spring/boot/properties/deployment/YamlListObjectHandler.java:211

                    });
                });
            }
        });
    }

    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);
        }
        ParameterizedType parameterizedType = (ParameterizedType) type;
        if (!DotNames.LIST.equals(parameterizedType.name())) {
            throw new IllegalArgumentException(ILLEGAL_ARGUMENT_MESSAGE);
        }
        if (parameterizedType.arguments().size() != 1) {
            throw new IllegalArgumentException(ILLEGAL_ARGUMENT_MESSAGE);
        }
        ClassInfo classInfo = index.getClassByName(parameterizedType.arguments().get(0).name());
        if (classInfo == null) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Mark the element class public (for nested classes: public static class ...)
  2. Move the class to its own top-level public file
  3. Use a @ConfigMapping interface instead of class-based config

Example fix

// before
class ServerConfig { ... }
// after
public class ServerConfig { ... }
Defensive patterns

Strategy: validation

Validate before calling

static void requirePublicClass(Class<?> c) {
    if (!java.lang.reflect.Modifier.isPublic(c.getModifiers()))
        throw new IllegalStateException(c + " must be public for YAML config binding");
}

Type guard

boolean isPublicConcrete(Class<?> c) {
    return java.lang.reflect.Modifier.isPublic(c.getModifiers()) && !c.isInterface();
}

Try / catch

catch (IllegalArgumentException e) { if (e.getMessage().contains("must be a public class")) { /* make class public */ } throw e; }

Prevention

When it happens

Trigger: A List<SomeClass> config member where SomeClass is package-private, protected, or private (e.g. a nested class without the public modifier) in a @ConfigProperties-processed class.

Common situations: Nested helper classes inside config classes declared without 'public', common when the nested class is only used internally.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/3a31739542891129. Report an issue: GitHub.