quarkusio/quarkus · error · IllegalArgumentException

Method ${method} of interface ${interface} is not a getter m

Error message

Method ${method} of interface ${interface} is not a getter method since it returns void

What it means

When a derived query returns a non-entity interface projection, Quarkus's spring-data-jpa extension generates an implementation class of that interface in generateCustomResultTypes. Every method in the interface is treated as a JavaBean getter (getX/isX mapped to a property), so a getter-shaped method returning void cannot be backed by any entity field and the build fails with this IllegalArgumentException.

Source

Thrown at extensions/spring-data-jpa/deployment/src/main/java/io/quarkus/spring/data/deployment/generate/DerivedMethodsAdder.java:441

        ClassInfo interfaceInfo = index.getClassByName(interfaceName);

        Gizmo gizmo = Gizmo.create(nonBeansClassOutput);
        gizmo.class_(implName.toString(), implClassCreator -> {
            implClassCreator.implements_(ClassDesc.of(interfaceName.toString()));

            // Add default constructor
            implClassCreator.defaultConstructor();

            Map<String, FieldDesc> fields = new HashMap<>(3);

            for (MethodInfo method : interfaceInfo.methods()) {
                String getterName = method.name();
                String propertyName = JavaBeanUtil.getPropertyNameFromGetter(getterName);

                Type returnType = method.returnType();
                if (returnType.kind() == Type.Kind.VOID) {
                    throw new IllegalArgumentException("Method " + method.name() + " of interface " + interfaceName
                            + " is not a getter method since it returns void");
                }
                DotName fieldTypeName = returnType.name();

                FieldDesc field = implClassCreator.field(propertyName, ifc -> {
                    ifc.setType(GenerationUtil.toClassDesc(fieldTypeName.toString()));
                });

                // create getter (based on the interface)
                MethodTypeDesc getterMtd = GenerationUtil.toMethodTypeDesc(returnType.name().toString());
                implClassCreator.method(getterName, mc -> {
                    mc.setType(getterMtd);
                    mc.public_();
                    mc.body(bc -> {
                        bc.return_(bc.get(mc.this_().field(field)));
                    });
                });

View on GitHub (pinned to e1c734241f)

Solutions

  1. Remove the void method from the projection interface — it must contain only getters
  2. Give the method a proper return type matching an entity property (e.g. String getName())
  3. Move formatting/helper logic into the consuming service or a default method with a non-void, computed result if supported

Example fix

// before
interface PersonView {
    String getName();
    void printName();
}

// after
interface PersonView {
    String getName();
}
Defensive patterns

Strategy: validation

Validate before calling

// Ensure projection interfaces contain only non-void getters
static void checkProjection(Class<?> ifc) {
    for (Method m : ifc.getDeclaredMethods()) {
        if (m.getReturnType() == void.class)
            throw new IllegalStateException(m.getName() + " in " + ifc.getName() + " must not return void");
    }
}

Prevention

When it happens

Trigger: Declaring a projection interface containing e.g. void printName(); or any method whose name parses as a getter (JavaBeanUtil.getPropertyNameFromGetter succeeds) but whose return type kind is VOID — this also covers methods with parameters or abstract defaults that return void.

Common situations: Adding helper/formatting methods to a projection interface expecting a default method or DTO behavior; accidentally leaving a stub method with no return type; misunderstanding that projection interfaces must contain only pure getters.

Related errors


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