quarkusio/quarkus · error · DeploymentException
Body parameters (or non-annotated fields) are not allowed fo
Error message
Body parameters (or non-annotated fields) are not allowed for records. Make sure to annotate your record components with @Rest* or @*Param or that they can be injected as context objects.
What it means
Records used as parameters containers (@BeanParam or record endpoint parameters) must have every component resolvable to a REST parameter or context object. An unannotated component defaults to ParameterType.BODY, which is disallowed for records, so a DeploymentException is thrown.
Source
Thrown at independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/ServerEndpointIndexer.java:405
// records do not have field injection, we use their constructor, so field rules do not apply
boolean applyFieldRules = !currentClassInfo.isRecord();
// Keep build deterministic by using field order.
for (FieldInfo field : currentClassInfo.fieldsInDeclarationOrder()) {
// We don't do any injection in static fields
if (Modifier.isStatic(field.flags())) {
continue;
}
Map<DotName, AnnotationInstance> annotations = new HashMap<>();
for (AnnotationInstance i : field.annotations()) {
annotations.put(i.name(), i);
}
ServerIndexedParameter result = extractParameterInfo(currentClassInfo, actualEndpointInfo, null, existingConverters,
additionalReaders,
annotations, field.type(), "%s", new Object[] { field }, applyFieldRules, hasRuntimeConverters,
// We don't support annotation-less path params in injectable beans: only annotations
Collections.emptySet(), field.name(), EMPTY_STRING_ARRAY, new HashMap<>());
if (currentClassInfo.isRecord() && result.getType() == ParameterType.BODY) {
throw new DeploymentException(
"Body parameters (or non-annotated fields) are not allowed for records. Make sure to annotate your record components with @Rest* or @*Param or that they can be injected as context objects.");
}
if ((result.getType() != null) && (result.getType() != ParameterType.BEAN)) {
//BODY means no annotation, so for fields not injectable
fieldExtractors.put(field, result);
}
if (result.getType() == ParameterType.BEAN) {
beanParamFields.put(field, result);
// transform the bean param
// FIXME: pretty sure this doesn't work with generics
ClassInfo beanParamClassInfo = index.getClassByName(field.type().name());
InjectableBean injectableBean = scanInjectableBean(beanParamClassInfo, actualEndpointInfo,
existingConverters, additionalReaders, injectableBeans, hasRuntimeConverters);
// inherit form param requirement from field
if (injectableBean.isFormParamRequired()) {
currentInjectableBean.setFormParamRequired(true);
}
} else if (result.getType() == ParameterType.FORM) {View on GitHub (pinned to e1c734241f)
Solutions
- Annotate the component with @Rest* / @*Param (@QueryParam, @HeaderParam, @RestForm, etc.).
- If it is a context object (UriInfo, HttpHeaders, etc.) verify the type is auto-injectable — otherwise annotate or remove it.
- Remove the component; for request bodies use a plain class or a dedicated body parameter.
Example fix
// before
record UserSearch(String name, @QueryParam("limit") int limit) {}
// after
record UserSearch(@QueryParam("name") String name, @QueryParam("limit") int limit) {} Defensive patterns
Strategy: validation
Validate before calling
for (RecordComponent rc : UserSearch.class.getRecordComponents()) {
boolean annotated = java.util.Arrays.stream(rc.getAnnotations())
.anyMatch(a -> a.annotationType().getName().startsWith("org.jboss.resteasy.reactive")
|| a.annotationType().getName().endsWith("Param"));
if (!annotated) throw new IllegalStateException("Component " + rc.getName() + " needs a @Rest*/@*Param annotation");
} Prevention
- Never leave record components unannotated in parameter records.
- Team convention: records are parameter containers, not body DTOs.
- Review new record parameters for annotation coverage.
When it happens
Trigger: record MyParams(@QueryParam("q") String q, String unannotated) used as an endpoint parameter or @BeanParam — the unannotated component triggers the error.
Common situations: Adding a new record component without an annotation; using records as body/DTO holders assuming automatic binding; migrating from classes where an unannotated field meant body.
Related errors
- Class %s has no fields. Parameters containers are only suppo
- No annotations found on fields at '%s'. Annotations like `@Q
- Path '${method.getPath()}' of method '${currentClassInfo.nam
- Could not create converter for ${elementType} for ${builder.
- 'java.time.Instant' types must not be annotated with '@DateF
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/d50dcf9f0f7a373f.
Report an issue: GitHub.