quarkusio/quarkus · error · DeploymentException
Cannot directly return collections or arrays using JAXB. You
Error message
Cannot directly return collections or arrays using JAXB. You need to wrap it into a root element class. Problematic method is '{entry.getActualClassInfo().name}.{methodInfo.name}' What it means
When producing XML (application/xml) via JAXB, a JAX-RS resource method cannot directly return a Collection or array — JAXB requires a root element class to marshal. During deployment, RESTEasy Reactive's JAXB processor scans resource methods whose @Produces includes an XML media type, and if the effective return type is not JAXB-compatible (collection/array without a JAXB root), the build fails with this DeploymentException pointing at the offending method.
Source
Thrown at extensions/resteasy-reactive/rest-jaxb/deployment/src/main/java/io/quarkus/resteasy/reactive/jaxb/deployment/ResteasyReactiveJaxbProcessor.java:97
}
@BuildStep
void registerClassesToBeBound(ResteasyReactiveResourceMethodEntriesBuildItem resourceMethodEntries,
JaxRsResourceIndexBuildItem index,
BuildProducer<JaxbClassesToBeBoundBuildItem> classesToBeBoundBuildItemBuildProducer) {
Set<ClassInfo> classesInfo = new HashSet<>();
IndexView indexView = index.getIndexView();
for (ResteasyReactiveResourceMethodEntriesBuildItem.Entry entry : resourceMethodEntries.getEntries()) {
ResourceMethod resourceInfo = entry.getResourceMethod();
MethodInfo methodInfo = entry.getMethodInfo();
ClassInfo effectiveReturnType = getEffectiveClassInfo(methodInfo.returnType(), indexView);
if (effectiveReturnType != null) {
// When using "application/xml", the return type needs to be registered
if (producesXml(resourceInfo)) {
if (!isTypeCompatibleWithJaxb(methodInfo.returnType())) {
throw new DeploymentException(
"Cannot directly return collections or arrays using JAXB. You need to wrap it "
+ "into a root element class. Problematic method is '"
+ entry.getActualClassInfo().name() + "." + methodInfo.name() + "'");
}
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) {View on GitHub (pinned to e1c734241f)
Solutions
- Wrap the collection in a JAXB root element class (e.g. a @XmlRootElement wrapper holding a List<T> with @XmlElement wrapping)
- Change the endpoint to @Produces(MediaType.APPLICATION_JSON) if XML output is not actually needed
- Narrow the method's @Produces so it does not advertise XML if the return type cannot be marshalled
- Return a single @XmlRootElement entity instead of a collection, or stream via a custom MessageBodyWriter
Example fix
// before
@GET
@Produces(MediaType.APPLICATION_XML)
public List<User> users() { ... }
// after
@XmlRootElement(name = "users")
class Users {
@XmlElement(name = "user")
public List<User> users;
}
@GET
@Produces(MediaType.APPLICATION_XML)
public Users users() { ... } Defensive patterns
Strategy: type-guard
Validate before calling
static boolean isXmlCompatible(Class<?> rt) {
if (Collection.class.isAssignableFrom(rt) || rt.isArray()) return false;
return rt.isAnnotationPresent(jakarta.xml.bind.annotation.XmlRootElement.class);
}
// before declaring @Produces(APPLICATION_XML) on a method, assert:
if (!isXmlCompatible(method.getReturnType())) throw new IllegalStateException("Wrap the return type in a JAXB root element"); Type guard
static boolean hasJaxbRoot(Class<?> c) {
return c.isAnnotationPresent(jakarta.xml.bind.annotation.XmlRootElement.class);
} Try / catch
try {
deploy();
} catch (DeploymentException e) {
if (e.getMessage() != null && e.getMessage().contains("Cannot directly return collections or arrays using JAXB")) {
// wrap the return type named in the message
}
} Prevention
- Never return raw collections/arrays from @Produces(APPLICATION_XML) endpoints
- Use @XmlRootElement wrapper classes for XML list responses
- Match @Produces to what the return type can actually marshal
- Decide JSON vs XML per endpoint early in the design
When it happens
Trigger: A resource method annotated (explicitly or by negotiation) with @Produces(MediaType.APPLICATION_XML) (or application/*+xml) returns List<T>, Set<T>, T[], Response wrapping such, or any type failing the JAXB root-element compatibility check.
Common situations: Returning List<MyEntity> from an endpoint that defaults to XML because the client sends Accept: application/xml; switching @Produces from JSON to XML without restructuring the return type; copying JSON endpoints to XML endpoints.
Related errors
- Cannot handle collections or arrays as parameters using JAXB
- Error reading mapping file '<mappingFilePath>' ('<url>'): <e
- Parameter: ${i} of the constructor of class '${resourceDotNa
- Parameter: ${i} of the constructor of class '${resourceDotNa
- Unsupported type '${jaxRSAnnotationOfParam.name()}' used as
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/ded57d2722d1b478.
Report an issue: GitHub.