quarkusio/quarkus · error · IllegalArgumentException
Method + method.name() + of interface + ifaceDotName + i
Error message
Method + method.name() + of interface + ifaceDotName + is not a getter method since it returns void
What it means
Same interface-generation path: a non-default/static/private method on a @ConfigurationProperties interface that returns void cannot map to a config property, so IllegalArgumentException 'Method <name> of interface <iface> is not a getter method since it returns void' is thrown.
Source
Thrown at extensions/spring-boot-properties/deployment/src/main/java/io/quarkus/spring/boot/properties/deployment/InterfaceConfigurationPropertiesUtil.java:165
});
});
for (DotName ifaceDotName : allInterfaces) {
ClassInfo classInfo = index.getClassByName(ifaceDotName);
List<MethodInfo> methods = classInfo.methods();
for (MethodInfo method : methods) {
Type returnType = method.returnType();
short methodModifiers = method.flags();
if (isDefault(methodModifiers) || Modifier.isStatic(methodModifiers)
|| Modifier.isPrivate(methodModifiers)) {
continue;
}
if (!method.parameterTypes().isEmpty()) {
throw new IllegalArgumentException("Method " + method.name() + " of interface " + ifaceDotName
+ " is not a getter method since it defined parameters");
}
if (returnType.kind() == Type.Kind.VOID) {
throw new IllegalArgumentException("Method " + method.name() + " of interface " + ifaceDotName
+ " is not a getter method since it returns void");
}
NameAndDefaultValue nameAndDefaultValue = determinePropertyNameAndDefaultValue(method, namingStrategy);
String fullConfigName = prefixStr + "." + nameAndDefaultValue.getName();
cc.method(method.name(), mc -> {
mc.returning(ClassDesc.of(method.returnType().name().toString()));
mc.public_();
mc.body(bc -> {
if ((returnType.kind() == Type.Kind.CLASS)) {
ClassInfo returnTypeClassInfo = index.getClassByName(returnType.name());
if ((returnTypeClassInfo != null) && Modifier.isInterface(returnTypeClassInfo.flags())) {
String generatedSubInterfaceImp = generateImplementationForInterfaceConfigPropertiesRec(
originalInterface, returnTypeClassInfo,
fullConfigName, namingStrategy, interfaceToGeneratedClass);
View on GitHub (pinned to e1c734241f)
Solutions
- Remove the void method — config property interfaces are read-only.
- Give the method a body and mark it default if it is a helper.
- Convert mutators into setters on a separate POJO-based config class if mutation is genuinely needed.
Example fix
// before
public interface AppProps {
void setHost(String host);
}
// after
public interface AppProps {
String getHost();
} Defensive patterns
Strategy: validation
Validate before calling
for (Method m : AppProps.class.getMethods()) {
if (!m.isDefault() && !Modifier.isStatic(m.getModifiers())
&& m.getReturnType() == void.class) {
throw new IllegalStateException("Void method in config interface: " + m.getName());
}
} Prevention
- Config interfaces are read-only: no setters or void methods
- Use a POJO-based config class if mutable state is required
- Remove or default-implement any non-getter methods after porting from JavaBeans
When it happens
Trigger: Declaring a void-returning abstract method in an interface annotated with @ConfigurationProperties — e.g. a mutator-style method like setHost(String) or a command-style method; raised while generating the implementing class.
Common situations: Adding setters by habit from JavaBean style (config interfaces are read-only); porting interfaces that had write methods; leftover abstract methods after refactoring.
Related errors
- Method + method.name() + of interface + ifaceDotName + i
- Failed to open path tree with root %s
- Dev services for ${request.getName()} requires a startable s
- Name cannot start with '/':${name}
- The class (${name}) cannot be created during deployment.
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/dfd4ef79bcc7d7a2.
Report an issue: GitHub.