quarkusio/quarkus · error · DeploymentException

Cannot handle collections or arrays as parameters using JAXB

Error message

Cannot handle collections or arrays as parameters using JAXB. You need to wrap it into a root element class. Problematic parameter is '{parameter.name}' in the method '{entry.getActualClassInfo().name}.{methodInfo.name}'

What it means

For XML or multipart consumption, JAXB cannot unmarshal a request body that is a raw Collection or array — a root element class is required. The deployment processor checks each resource-method body parameter of methods whose @Consumes includes an XML media type or multipart, and fails the build with this DeploymentException naming the parameter and method when its type is not JAXB-compatible.

Source

Thrown at extensions/resteasy-reactive/rest-jaxb/deployment/src/main/java/io/quarkus/resteasy/reactive/jaxb/deployment/ResteasyReactiveJaxbProcessor.java:121

                    classesInfo.add(effectiveReturnType);
                }

                // When using "multipart/form-data", the parts that use "application/xml" need to be registered
                if (producesMultipart(resourceInfo)) {
                    classesInfo.addAll(getEffectivePartsUsingXml(effectiveReturnType, indexView));
                }
            }

            // If consumes "application/xml" or "multipart/form-data", we register all the classes of the parameters
            boolean consumesXml = consumesXml(resourceInfo);
            boolean consumesMultipart = consumesMultipart(resourceInfo);
            if (consumesXml || consumesMultipart) {
                for (MethodParameterInfo parameter : methodInfo.parameters()) {
                    if (!isParameterBody(parameter, resourceInfo)) {
                        continue;
                    }
                    if (!isTypeCompatibleWithJaxb(parameter.type())) {
                        throw new DeploymentException(
                                "Cannot handle collections or arrays as parameters using JAXB. You need to wrap it "
                                        + "into a root element class. Problematic parameter is '" + parameter.name()
                                        + "' in the method '" + entry.getActualClassInfo().name() + "." + methodInfo.name()
                                        + "'");
                    }

                    ClassInfo effectiveParameter = getEffectiveClassInfo(parameter.type(), indexView);
                    if (effectiveParameter != null) {
                        if (consumesXml) {
                            classesInfo.add(effectiveParameter);
                        } else if (consumesMultipart) {
                            classesInfo.addAll(getEffectivePartsUsingXml(effectiveParameter, indexView));
                        }
                    }
                }
            }
        }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Wrap the collection in a @XmlRootElement wrapper class and accept that as the body parameter
  2. Change @Consumes to MediaType.APPLICATION_JSON if the client actually sends JSON
  3. Restrict @Consumes so the method does not advertise XML/multipart if it cannot accept those payloads
  4. Use a custom Reader/MessageBodyReader if you must unmarshal collections for XML

Example fix

// before
@POST
@Consumes(MediaType.APPLICATION_XML)
public void create(List<User> users) { ... }

// after
@XmlRootElement(name = "users")
class UserList { @XmlElement(name = "user") public List<User> users; }

@POST
@Consumes(MediaType.APPLICATION_XML)
public void create(UserList users) { ... }
Defensive patterns

Strategy: type-guard

Validate before calling

static boolean isXmlCompatibleParam(Class<?> pt) {
    if (Collection.class.isAssignableFrom(pt) || pt.isArray()) return false;
    return pt.isAnnotationPresent(jakarta.xml.bind.annotation.XmlRootElement.class);
}
// for each @Consumes(APPLICATION_XML) body parameter:
if (!isXmlCompatibleParam(bodyParamType)) throw new IllegalStateException("Wrap parameter in a JAXB root element");

Type guard

static boolean isRootWrappable(Class<?> c) {
    return !(Collection.class.isAssignableFrom(c) || c.isArray());
}

Try / catch

try {
    deploy();
} catch (DeploymentException e) {
    if (e.getMessage() != null && e.getMessage().contains("Cannot handle collections or arrays as parameters using JAXB")) {
        // wrap the parameter named in the message
    }
}

Prevention

When it happens

Trigger: A resource method with @Consumes(MediaType.APPLICATION_XML) (or multipart form) declares a body parameter of type List<T>, Collection<T>, or T[] that lacks a JAXB root element.

Common situations: POST/PUT endpoints accepting JSON-styled list payloads but declaring XML consumption; multipart endpoints with array-typed parts; porting JSON endpoints to XML without changing the parameter model.

Related errors


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