quarkusio/quarkus · error · IllegalArgumentException

@Query annotation for ${method} does not use fields from ${i

Error message

@Query annotation for ${method} does not use fields from ${interface}

What it means

For interface-based projections over custom @Query results, every selected column in the query must correspond to a getter/field of the projection interface, and conversely the fields the extension recorded for the query must exist in the interface. When a field name recorded from the @Query is not found among the projection interface's generated fields, this error is thrown at build time.

Source

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

            for (Map.Entry<String, List<String>> queryMethod : queryMethods.entrySet().stream()
                    .sorted(Map.Entry.comparingByKey()).toList()) {
                MethodTypeDesc convertMtd = GenerationUtil.toMethodTypeDesc(implName.toString(), Object[].class.getName());
                implClassCreator.staticMethod("convert_" + queryMethod.getKey(), smc -> {
                    smc.setType(convertMtd);
                    smc.public_();
                    ParamVar arrayParam = smc.parameter("input");

                    smc.body(bc -> {
                        LocalVar newObject = bc.localVar("newObject",
                                bc.new_(ClassDesc.of(implName.toString())));

                        // Use field names in the query-declared order
                        List<String> queryNames = queryMethod.getValue();

                        for (int i = 0; i < queryNames.size(); i++) {
                            FieldDesc f = fields.get(queryNames.get(i));
                            if (f == null) {
                                throw new IllegalArgumentException("@Query annotation for " + queryMethod.getKey()
                                        + " does not use fields from " + interfaceName);
                            } else {
                                bc.set(newObject.field(f),
                                        castReturnValue(bc, arrayParam.elem(i), f.type()));
                            }
                        }
                        bc.return_(newObject);
                    });
                });
            }
        });
    }

    private Expr castReturnValue(BlockCreator bc, Expr resultHandle, ClassDesc type) {
        String typeDesc = type.descriptorString();
        switch (typeDesc) {
            case "I":
                resultHandle = bc.invokeStatic(

View on GitHub (pinned to e1c734241f)

Solutions

  1. Align the JPQL SELECT aliases with the projection interface getter names (e.g. SELECT u.name AS name)
  2. Rename the interface getter to match the selected column/alias
  3. Add the missing getter for each selected column
  4. Run the query mentally and enumerate its selected expressions, ensuring each has a matching interface property

Example fix

// before
@Query("SELECT u.userName FROM User u")
interface-based return UserView { String getName(); }

// after
@Query("SELECT u.userName AS name FROM User u")
List<UserView> ...; // UserView.getName() now matches alias 'name'
Defensive patterns

Strategy: validation

Validate before calling

// every alias in the SELECT clause must have a matching getter in the projection interface
// e.g. SELECT u.userName AS name  <=>  String getName();

Prevention

When it happens

Trigger: The list of field names parsed from the @Query SELECT clause contains a name for which no matching getter exists on the projection interface (fields.get(name) returns null) in generateCustomResultTypes.

Common situations: Query selects u.userName but interface getter is getName(); typos in alias names; changing the interface getters without updating the query, or vice versa; queries selecting entities mixed with scalars.

Related errors


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