quarkusio/quarkus · error · IllegalArgumentException
Setter '' + setterName + '' of class '' + configClassInfo +
Error message
Setter '' + setterName + '' of class '' + configClassInfo + '' must be public
What it means
When a setter method exists for a configuration field but is not public, the framework cannot invoke it reflectively at build time to populate the config object. Non-public setters are therefore rejected with this IllegalArgumentException.
Source
Thrown at extensions/spring-boot-properties/deployment/src/main/java/io/quarkus/spring/boot/properties/deployment/ClassConfigurationPropertiesUtil.java:298
String setterName = JavaBeanUtil.getSetterName(field.name());
Type fieldType = field.type();
MethodInfo setter = currentClassInHierarchy.method(setterName, fieldType);
if (setter == null) {
if (!Modifier.isPublic(field.flags()) || Modifier.isFinal(field.flags())) {
String message = "Configuration properties class '" + configClassInfo
+ "' does not have a setter for field '"
+ field.name() + "' nor is the field a public non-final field.";
if (failOnMismatchingMember) {
throw new IllegalArgumentException(message);
} else {
LOGGER.warn(message + " It will therefore be ignored.");
continue;
}
}
useFieldAccess = true;
}
if (!useFieldAccess && !Modifier.isPublic(setter.flags())) {
throw new IllegalArgumentException(
"Setter '" + setterName + "' of class '" + configClassInfo + "' must be public");
}
/*
* If the object is part of the application we are dealing with a nested object
* What we do is simply recursively build it up based by adding the field name to the config name prefix
*/
DotName fieldTypeDotName = fieldType.name();
ClassInfo fieldTypeClassInfo = applicationIndex.getClassByName(fieldType.name());
if (fieldTypeClassInfo != null) {
if (DotNames.ENUM.equals(fieldTypeClassInfo.superName())) {
populateTypicalProperty(bc, configObject, configPropertyBuildItemCandidates,
currentClassInHierarchy, field, useFieldAccess, fieldType, setter, configParam,
getFullConfigName(prefixStr, namingStrategy, field));
// we need to register the 'valueOf' method of the enum for reflection because
// that is the method that SmallryeConfig uses for conversion of enums
List<MethodInfo> methods = fieldTypeClassInfo.methods();View on GitHub (pinned to e1c734241f)
Solutions
- Make the setter method public.
- Alternatively make the field public non-final so field access is used instead of the setter.
- Rename the accessor if it is not actually intended as the bound setter.
Example fix
// before
void setName(String name) { this.name = name; }
// after
public void setName(String name) { this.name = name; } Defensive patterns
Strategy: validation
Validate before calling
static void checkPublicSetters(Class<?> props) {
for (Method m : props.getDeclaredMethods()) {
if (m.getName().startsWith("set") && m.getParameterCount() == 1
&& !Modifier.isPublic(m.getModifiers()))
throw new IllegalArgumentException(m + " must be public");
}
} Prevention
- Keep all config setters public.
- Avoid fluent setters returning 'this' with reduced visibility in properties classes.
- Re-check access modifiers after refactoring accessor visibility.
When it happens
Trigger: populateConfigObject resolves the setter for a field and, when useFieldAccess is false, checks Modifier.isPublic(setter.flags()); a protected/package-private/private setter triggers the throw.
Common situations: Fluent setters returning 'this' made package-private; setters narrowed to protected for subclass-only access during refactoring; generated classes with restricted accessors.
Related errors
- Class '' + configObjectClassStr + '' which is annotated with
- Class + configPropertiesClassInfo + which is annotated wit
- Configuration properties class '' + configClassInfo + '' doe
- Nested configuration class ' + fieldTypeClassInfo + ' must b
- Method '%s' annotated with '@Funq' declared in the class '%s
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/14a3e2fef0cdd5fb.
Report an issue: GitHub.