{"record":{"id":"bea3eed88dff9cd3","repo":"quarkusio/quarkus","slug":"formparam-and-restform-cannot-be-used-in-a-r","errorCode":null,"errorMessage":"'@FormParam' and '@RestForm' cannot be used in a resource method that contains a body parameter. Offending method is '%s#%s'","messagePattern":"'@FormParam' and '@RestForm' cannot be used in a resource method that contains a body parameter\\. Offending method is '(.+?)#(.+?)'","errorType":"validation","errorClass":"DeploymentException","httpStatus":null,"severity":"error","filePath":"independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java","lineNumber":668,"sourceCode":"                methodParameters[i] = createMethodParameter(currentClassInfo, actualEndpointInfo, encoded, paramType,\n                        parameterResult, name, defaultValue, type, elementType, single,\n                        AsmUtil.getSignature(paramType, typeArgMapper), fileFormNames);\n\n                if (type == ParameterType.BEAN\n                        || type == ParameterType.MULTI_PART_FORM) {\n                    // transform the bean param\n                    formParamRequired |= handleBeanParam(actualEndpointInfo, paramType, methodParameters, i, fileFormNames);\n                } else if (type == ParameterType.FORM || type == ParameterType.MULTI_PART_DATA_INPUT\n                        || type == ParameterType.ENTITY_PART_LIST) {\n                    formParamRequired = true;\n                }\n            }\n\n            if (formParamRequired) {\n                if (bodyParamType != null\n                        && !bodyParamType.name().equals(ResteasyReactiveDotNames.MULTI_VALUED_MAP)\n                        && !bodyParamType.name().equals(ResteasyReactiveDotNames.STRING)) {\n                    throw new DeploymentException(String.format(\n                            \"'@FormParam' and '@RestForm' cannot be used in a resource method that contains a body parameter. Offending method is \"\n                                    + \"'%s#%s'\",\n                            currentMethodInfo.declaringClass().name(), currentMethodInfo));\n                }\n                boolean validConsumes = false;\n                if (consumes != null && consumes.length > 0) {\n                    for (String c : consumes) {\n                        if (c.startsWith(MediaType.MULTIPART_FORM_DATA)\n                                || c.startsWith(MediaType.APPLICATION_FORM_URLENCODED)) {\n                            validConsumes = true;\n                            break;\n                        }\n                    }\n                    // TODO: does it make sense to default to MediaType.MULTIPART_FORM_DATA when no consumes is set?\n                    if (!validConsumes) {\n                        throw new DeploymentException(String.format(\n                                \"'@FormParam' and '@RestForm' can only be used on methods annotated with '@Consumes(MediaType.MULTIPART_FORM_DATA)' '@Consumes(MediaType.APPLICATION_FORM_URLENCODED)'. Offending method is \"\n                                        + \"'%s#%s'\",","sourceCodeStart":650,"sourceCodeEnd":686,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java#L650-L686","documentation":"RESTEasy Reactive rejects resource methods that combine @FormParam/@RestForm parameters with a body parameter (unless the body is MultiValuedMap or String). Form data itself is the request body, so a second body parameter makes the request entity ambiguous and cannot be mapped. The deployment-time check in EndpointIndexer.createResourceMethod fails fast with a DeploymentException naming the offending method.","triggerScenarios":"A JAX-RS/REST endpoint method declares both form parameter annotations (e.g. @RestForm String name) and another non-form body parameter (e.g. an unannotated POJO, InputStream, byte[], or @MultipartForm type other than MultiValuedMap/String), then the Quarkus application is built/deployed.","commonSituations":"Mixing old servlet-style form parsing with a JSON/POJO body; migrating a method to @RestForm while leaving an existing body parameter in place; accidentally adding @RestForm fields to a method that already accepts a @MultipartForm or entity object.","solutions":["Remove the separate body parameter and model its data as @RestForm fields instead","Keep the body parameter and remove all @FormParam/@RestForm annotations, passing form values through the body object (e.g. a MultiValuedMap or @MultipartForm bean)","If using MultiValuedMap, change the body parameter type to MultiValuedMap<String,String>, which is explicitly allowed alongside form params"],"exampleFix":"// before\n@POST\n@Consumes(MediaType.MULTIPART_FORM_DATA)\npublic String upload(@RestForm String name, MyDto dto) { ... }\n// after\n@POST\n@Consumes(MediaType.MULTIPART_FORM_DATA)\npublic String upload(@RestForm String name, @RestForm String other) { ... }","handlingStrategy":"validation","validationCode":"// Deployment-time check: scan resource methods before build\nMethod[] methods = MyResource.class.getDeclaredMethods();\nfor (Method m : methods) {\n    boolean hasForm = java.util.Arrays.stream(m.getParameterAnnotations())\n        .flatMap(java.util.Arrays::stream)\n        .anyMatch(a -> a.annotationType().getSimpleName().matches(\"(FormParam|RestForm)\"));\n    long bodyParams = java.util.Arrays.stream(m.getParameters())\n        .filter(p -> java.util.Arrays.stream(p.getAnnotations())\n            .noneMatch(a -> a.annotationType().getSimpleName().matches(\"(PathParam|QueryParam|HeaderParam|FormParam|CookieParam|BeanParam|Context|Rest.*|MultipartForm)\")))\n        .count();\n    if (hasForm && bodyParams > 0) throw new IllegalStateException(\"Form params + body param in \" + m);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep one data-source strategy per endpoint: either form fields or a body object, never both","Use @MultipartForm beans or MultiValuedMap to bundle form data instead of mixing parameters","Add an ArchUnit or annotation-processing check in CI to catch mixed form/body signatures","Review resource method signatures when migrating between form and JSON payloads"],"tags":["quarkus","resteasy-reactive","form-params","deployment"],"backgroundTag":"form-param-with-body-conflict","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}