{"record":{"id":"86036685b48f6e91","repo":"quarkusio/quarkus","slug":"cannot-handle-collections-or-arrays-as-parameters","errorCode":null,"errorMessage":"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}'","messagePattern":"Cannot handle collections or arrays as parameters using JAXB\\. You need to wrap it into a root element class\\. Problematic parameter is '(.+?)' in the method '(.+?)\\.(.+?)'","errorType":"exception","errorClass":"DeploymentException","httpStatus":null,"severity":"error","filePath":"extensions/resteasy-reactive/rest-jaxb/deployment/src/main/java/io/quarkus/resteasy/reactive/jaxb/deployment/ResteasyReactiveJaxbProcessor.java","lineNumber":121,"sourceCode":"                    classesInfo.add(effectiveReturnType);\n                }\n\n                // When using \"multipart/form-data\", the parts that use \"application/xml\" need to be registered\n                if (producesMultipart(resourceInfo)) {\n                    classesInfo.addAll(getEffectivePartsUsingXml(effectiveReturnType, indexView));\n                }\n            }\n\n            // If consumes \"application/xml\" or \"multipart/form-data\", we register all the classes of the parameters\n            boolean consumesXml = consumesXml(resourceInfo);\n            boolean consumesMultipart = consumesMultipart(resourceInfo);\n            if (consumesXml || consumesMultipart) {\n                for (MethodParameterInfo parameter : methodInfo.parameters()) {\n                    if (!isParameterBody(parameter, resourceInfo)) {\n                        continue;\n                    }\n                    if (!isTypeCompatibleWithJaxb(parameter.type())) {\n                        throw new DeploymentException(\n                                \"Cannot handle collections or arrays as parameters using JAXB. You need to wrap it \"\n                                        + \"into a root element class. Problematic parameter is '\" + parameter.name()\n                                        + \"' in the method '\" + entry.getActualClassInfo().name() + \".\" + methodInfo.name()\n                                        + \"'\");\n                    }\n\n                    ClassInfo effectiveParameter = getEffectiveClassInfo(parameter.type(), indexView);\n                    if (effectiveParameter != null) {\n                        if (consumesXml) {\n                            classesInfo.add(effectiveParameter);\n                        } else if (consumesMultipart) {\n                            classesInfo.addAll(getEffectivePartsUsingXml(effectiveParameter, indexView));\n                        }\n                    }\n                }\n            }\n        }\n","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/resteasy-reactive/rest-jaxb/deployment/src/main/java/io/quarkus/resteasy/reactive/jaxb/deployment/ResteasyReactiveJaxbProcessor.java#L103-L139","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Wrap the collection in a @XmlRootElement wrapper class and accept that as the body parameter","Change @Consumes to MediaType.APPLICATION_JSON if the client actually sends JSON","Restrict @Consumes so the method does not advertise XML/multipart if it cannot accept those payloads","Use a custom Reader/MessageBodyReader if you must unmarshal collections for XML"],"exampleFix":"// before\n@POST\n@Consumes(MediaType.APPLICATION_XML)\npublic void create(List<User> users) { ... }\n\n// after\n@XmlRootElement(name = \"users\")\nclass UserList { @XmlElement(name = \"user\") public List<User> users; }\n\n@POST\n@Consumes(MediaType.APPLICATION_XML)\npublic void create(UserList users) { ... }","handlingStrategy":"type-guard","validationCode":"static boolean isXmlCompatibleParam(Class<?> pt) {\n    if (Collection.class.isAssignableFrom(pt) || pt.isArray()) return false;\n    return pt.isAnnotationPresent(jakarta.xml.bind.annotation.XmlRootElement.class);\n}\n// for each @Consumes(APPLICATION_XML) body parameter:\nif (!isXmlCompatibleParam(bodyParamType)) throw new IllegalStateException(\"Wrap parameter in a JAXB root element\");","typeGuard":"static boolean isRootWrappable(Class<?> c) {\n    return !(Collection.class.isAssignableFrom(c) || c.isArray());\n}","tryCatchPattern":"try {\n    deploy();\n} catch (DeploymentException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"Cannot handle collections or arrays as parameters using JAXB\")) {\n        // wrap the parameter named in the message\n    }\n}","preventionTips":["Avoid List<T>/array body parameters on XML-consuming endpoints","Introduce @XmlRootElement wrapper DTOs for XML payloads","Keep @Consumes honest with respect to the declared parameter type","Use JSON for collection-heavy APIs unless XML is a hard requirement"],"tags":["jaxb","quarkus","xml","resteasy-reactive","request-body"],"backgroundTag":"jaxb-root-element-required","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}