quarkusio/quarkus · error · DeploymentException

'@FormParam' and '@RestForm' can only be used on methods ann

Error message

'@FormParam' and '@RestForm' can only be used on methods annotated with '@Consumes(MediaType.MULTIPART_FORM_DATA)' '@Consumes(MediaType.APPLICATION_FORM_URLENCODED)'. Offending method is '%s#%s'

What it means

Methods using @FormParam/@RestForm must declare @Consumes of either multipart/form-data or application/x-www-form-urlencoded, because form parameters can only be extracted from those media types. EndpointIndexer validates the method's @Produces/@Consumes metadata during deployment and throws if no valid consumes value is present.

Source

Thrown at independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java:684

                        && !bodyParamType.name().equals(ResteasyReactiveDotNames.MULTI_VALUED_MAP)
                        && !bodyParamType.name().equals(ResteasyReactiveDotNames.STRING)) {
                    throw new DeploymentException(String.format(
                            "'@FormParam' and '@RestForm' cannot be used in a resource method that contains a body parameter. Offending method is "
                                    + "'%s#%s'",
                            currentMethodInfo.declaringClass().name(), currentMethodInfo));
                }
                boolean validConsumes = false;
                if (consumes != null && consumes.length > 0) {
                    for (String c : consumes) {
                        if (c.startsWith(MediaType.MULTIPART_FORM_DATA)
                                || c.startsWith(MediaType.APPLICATION_FORM_URLENCODED)) {
                            validConsumes = true;
                            break;
                        }
                    }
                    // TODO: does it make sense to default to MediaType.MULTIPART_FORM_DATA when no consumes is set?
                    if (!validConsumes) {
                        throw new DeploymentException(String.format(
                                "'@FormParam' and '@RestForm' can only be used on methods annotated with '@Consumes(MediaType.MULTIPART_FORM_DATA)' '@Consumes(MediaType.APPLICATION_FORM_URLENCODED)'. Offending method is "
                                        + "'%s#%s'",
                                currentMethodInfo.declaringClass().name(), currentMethodInfo));
                    }
                }
            }

            Type methodContextReturnTypeOrReturnType = methodContext.containsKey(METHOD_CONTEXT_CUSTOM_RETURN_TYPE_KEY)
                    ? (Type) methodContext.get(METHOD_CONTEXT_CUSTOM_RETURN_TYPE_KEY)
                    : currentMethodInfo.returnType();
            if (REST_RESPONSE.equals(methodContextReturnTypeOrReturnType.name())
                    && (methodContextReturnTypeOrReturnType.kind() == Kind.CLASS)) {
                log.warnf("Method '%s' of Resource class '%s' returns RestResponse but does not declare a generic type. "
                        + "It is strongly advised to define the generic type otherwise the behavior could be unpredictable",
                        currentMethodInfo, currentMethodInfo.declaringClass().name());
            }
            Type nonAsyncReturnType = getNonAsyncReturnType(methodContextReturnTypeOrReturnType);
            addWriterForType(additionalWriters, nonAsyncReturnType);

View on GitHub (pinned to e1c734241f)

Solutions

  1. Add or correct @Consumes on the method: @Consumes(MediaType.MULTIPART_FORM_DATA) for file/multipart uploads or @Consumes(MediaType.APPLICATION_FORM_URLENCODED) for plain form posts
  2. Remove @FormParam/@RestForm parameters if the method really consumes JSON or another content type
  3. Check for inherited/class-level @Consumes annotations that restrict the allowed media types

Example fix

// before
@POST
public String submit(@RestForm String name) { ... }
// after
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public String submit(@RestForm String name) { ... }
Defensive patterns

Strategy: validation

Validate before calling

Consumes consumes = MyResource.class.getMethod("submit", String.class)
    .getAnnotation(Consumes.class);
boolean ok = consumes != null && java.util.Arrays.stream(consumes.value()).anyMatch(
    mt -> mt.equals(MediaType.MULTIPART_FORM_DATA) || mt.equals(MediaType.APPLICATION_FORM_URLENCODED));
if (!ok) throw new IllegalStateException("Form-param method must consume multipart/form-data or application/x-www-form-urlencoded");

Prevention

When it happens

Trigger: A resource method has @FormParam/@RestForm parameters but its @Consumes annotation lists a media type other than MULTIPART_FORM_DATA or APPLICATION_FORM_URLENCODED (e.g. application/json), or omits @Consumes entirely while a class-level @Consumes application/json applies.

Common situations: Forgetting @Consumes when adding form params; a class-level @Consumes(MediaType.APPLICATION_JSON) overriding expectations; form params left over after changing a method from form submission to JSON body handling.

Related errors


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