{"record":{"id":"d50dcf9f0f7a373f","repo":"quarkusio/quarkus","slug":"body-parameters-or-non-annotated-fields-are-not","errorCode":null,"errorMessage":"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.","messagePattern":"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\\.","errorType":"validation","errorClass":"DeploymentException","httpStatus":null,"severity":"error","filePath":"independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/ServerEndpointIndexer.java","lineNumber":405,"sourceCode":"        // records do not have field injection, we use their constructor, so field rules do not apply\n        boolean applyFieldRules = !currentClassInfo.isRecord();\n        // Keep build deterministic by using field order.\n        for (FieldInfo field : currentClassInfo.fieldsInDeclarationOrder()) {\n            // We don't do any injection in static fields\n            if (Modifier.isStatic(field.flags())) {\n                continue;\n            }\n            Map<DotName, AnnotationInstance> annotations = new HashMap<>();\n            for (AnnotationInstance i : field.annotations()) {\n                annotations.put(i.name(), i);\n            }\n            ServerIndexedParameter result = extractParameterInfo(currentClassInfo, actualEndpointInfo, null, existingConverters,\n                    additionalReaders,\n                    annotations, field.type(), \"%s\", new Object[] { field }, applyFieldRules, hasRuntimeConverters,\n                    // We don't support annotation-less path params in injectable beans: only annotations\n                    Collections.emptySet(), field.name(), EMPTY_STRING_ARRAY, new HashMap<>());\n            if (currentClassInfo.isRecord() && result.getType() == ParameterType.BODY) {\n                throw new DeploymentException(\n                        \"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.\");\n            }\n            if ((result.getType() != null) && (result.getType() != ParameterType.BEAN)) {\n                //BODY means no annotation, so for fields not injectable\n                fieldExtractors.put(field, result);\n            }\n            if (result.getType() == ParameterType.BEAN) {\n                beanParamFields.put(field, result);\n                // transform the bean param\n                // FIXME: pretty sure this doesn't work with generics\n                ClassInfo beanParamClassInfo = index.getClassByName(field.type().name());\n                InjectableBean injectableBean = scanInjectableBean(beanParamClassInfo, actualEndpointInfo,\n                        existingConverters, additionalReaders, injectableBeans, hasRuntimeConverters);\n                // inherit form param requirement from field\n                if (injectableBean.isFormParamRequired()) {\n                    currentInjectableBean.setFormParamRequired(true);\n                }\n            } else if (result.getType() == ParameterType.FORM) {","sourceCodeStart":387,"sourceCodeEnd":423,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/ServerEndpointIndexer.java#L387-L423","documentation":"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.","triggerScenarios":"record MyParams(@QueryParam(\"q\") String q, String unannotated) used as an endpoint parameter or @BeanParam — the unannotated component triggers the error.","commonSituations":"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.","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."],"exampleFix":"// before\nrecord UserSearch(String name, @QueryParam(\"limit\") int limit) {}\n\n// after\nrecord UserSearch(@QueryParam(\"name\") String name, @QueryParam(\"limit\") int limit) {}","handlingStrategy":"validation","validationCode":"for (RecordComponent rc : UserSearch.class.getRecordComponents()) {\n    boolean annotated = java.util.Arrays.stream(rc.getAnnotations())\n        .anyMatch(a -> a.annotationType().getName().startsWith(\"org.jboss.resteasy.reactive\")\n                   || a.annotationType().getName().endsWith(\"Param\"));\n    if (!annotated) throw new IllegalStateException(\"Component \" + rc.getName() + \" needs a @Rest*/@*Param annotation\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never leave record components unannotated in parameter records.","Team convention: records are parameter containers, not body DTOs.","Review new record parameters for annotation coverage."],"tags":["resteasy-reactive","quarkus","records","beanparam","deployment-failure"],"backgroundTag":"unannotated-record-component","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}