quarkusio/quarkus · error · DeploymentException

No annotations found on fields at '%s'. Annotations like `@Q

Error message

No annotations found on fields at '%s'. Annotations like `@QueryParam` should be used in fields, not in methods.

What it means

RESTEasy Reactive extracts request parameter values from annotated FIELDS of @BeanParam containers. If no field is annotated but the class has methods, it concludes the annotations (@QueryParam, @HeaderParam, etc.) were placed on methods and throws this DeploymentException.

Source

Thrown at independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/ServerEndpointIndexer.java:313

        return null;
    }

    @Override
    protected boolean handleBeanParam(ClassInfo actualEndpointInfo, Type paramType, MethodParameter[] methodParameters, int i,
            Set<String> fileFormNames) {
        ClassInfo beanParamClassInfo = index.getClassByName(paramType.name());
        InjectableBean injectableBean = scanInjectableBean(beanParamClassInfo,
                actualEndpointInfo,
                existingConverters, additionalReaders, injectableBeans, hasRuntimeConverters);
        if ((injectableBean.getFieldExtractorsCount() == 0) && !injectableBean.isInjectionRequired()) {
            long declaredMethodsCount = beanParamClassInfo.methods().stream()
                    .filter(m -> !m.name().equals("<init>") && !m.name().equals("<clinit>")).count();
            if (declaredMethodsCount == 0) {
                throw new DeploymentException(String.format(
                        "Class %s has no fields. Parameters containers are only supported if they have at least one annotated field.",
                        beanParamClassInfo.name()));
            } else {
                throw new DeploymentException(String.format("No annotations found on fields at '%s'. "
                        + "Annotations like `@QueryParam` should be used in fields, not in methods.",
                        beanParamClassInfo.name()));
            }

        }
        fileFormNames.addAll(injectableBean.getFileFormNames());
        return injectableBean.isFormParamRequired();
    }

    @Override
    protected boolean doesMethodHaveBlockingSignature(MethodInfo info) {
        for (var i : methodScanners) {
            if (i.isMethodSignatureAsync(info)) {
                return false;
            }
        }
        return true;
    }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Move the REST parameter annotations from methods onto the corresponding fields.
  2. Use a record with annotated components for a compact immutable container.
  3. Delete the method annotations if they were added by mistake.

Example fix

// before
class Filters {
    @QueryParam("sort")
    public void setSort(String sort) { this.sort = sort; }
}

// after
class Filters {
    @QueryParam("sort")
    public String sort;
}
Defensive patterns

Strategy: validation

Validate before calling

boolean anyAnnotatedField = false;
for (java.lang.reflect.Field f : Filters.class.getDeclaredFields()) {
    if (f.isAnnotationPresent(jakarta.ws.rs.QueryParam.class)) { anyAnnotatedField = true; break; }
}
if (!anyAnnotatedField) throw new IllegalStateException("@QueryParam must be on fields, not methods");

Prevention

When it happens

Trigger: Declaring class MyParams { @QueryParam("q") void setQ(String q) {...} } or putting @QueryParam on a getter, then using MyParams as a @BeanParam.

Common situations: Migrating from frameworks that bind via annotated setters; IDE-generated getters/setters receiving the annotations; assuming Spring-MVC-style property binding works here.

Related errors


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