{"record":{"id":"434b32cd06a51fe0","repo":"apache/maven","slug":"duplicated-tag-roottag","errorCode":null,"errorMessage":"Duplicated tag: '${rootTag}'","messagePattern":"Duplicated tag: '(.+?)'","errorType":"exception","errorClass":"XMLStreamException","httpStatus":null,"severity":"error","filePath":"src/mdo/reader-stax.vm","lineNumber":279,"sourceCode":"     */\n#if ( $locationTracking )\n    public ${root.name} read(XMLStreamReader parser, boolean strict, InputSource inputSrc) throws XMLStreamException {\n#else\n    public ${root.name} read(XMLStreamReader parser, boolean strict) throws XMLStreamException {\n#end\n#if ( $needXmlContext )\n        Deque<Object> context = new ArrayDeque<>();\n#end\n        $rootUcapName $rootLcapName = null;\n        int eventType = parser.getEventType();\n        boolean parsed = false;\n        while (eventType != XMLStreamReader.END_DOCUMENT) {\n            if (eventType == XMLStreamReader.START_ELEMENT) {\n                if (strict && ! \"${rootTag}\".equals(parser.getLocalName())) {\n                    throw new XMLStreamException(\"Expected root element '${rootTag}' but found '\" + parser.getName() + \"'\", parser.getLocation(), null);\n                } else if (parsed) {\n                    // fallback, already expected a XMLStreamException due to invalid XML\n                    throw new XMLStreamException(\"Duplicated tag: '${rootTag}'\", parser.getLocation(), null);\n                }\n#if ( $locationTracking )\n                $rootLcapName = parse${rootUcapName}(parser, strict, parser.getNamespaceURI(), inputSrc);\n#elseif ( $needXmlContext )\n                $rootLcapName = parse${rootUcapName}(parser, strict, parser.getNamespaceURI(), context);\n#else\n                $rootLcapName = parse${rootUcapName}(parser, strict, parser.getNamespaceURI());\n#end\n                parsed = true;\n            }\n            eventType = parser.next();\n        }\n        if (parsed) {\n            return $rootLcapName;\n        }\n            throw new XMLStreamException(\"Expected root element '${rootTag}' but found no element at all: invalid XML document\", parser.getLocation(), null);\n    } //-- ${root.name} read(XMLStreamReader, boolean)\n","sourceCodeStart":261,"sourceCodeEnd":297,"githubUrl":"https://github.com/apache/maven/blob/e4093d4e120eac99d6bdce5ba67cace2f3085c97/src/mdo/reader-stax.vm#L261-L297","documentation":"After read() has parsed one root element, its event loop keeps scanning to END_DOCUMENT; a second START_ELEMENT at the top level means the stream contains more than one root element. Well-formed XML has exactly one root, so a conforming STAX parser normally rejects such input first - the template comment marks this throw as a fallback for lenient parsers or malformed streams that surface the second root as an event.","triggerScenarios":"read() over a stream holding two concatenated XML documents (e.g. two pom files appended together); a custom or lenient XMLStreamReader that does not enforce single-root well-formedness; also reachable with strict=false after one root was parsed and another top-level element follows.","commonSituations":"CI logs or test fixtures that join several XML snippets into one stream; files truncated and later appended; streaming pipelines that flush multiple documents into one channel; concatenation tools that merge XML without a wrapper element.","solutions":["Fix the input so it contains exactly one top-level element - wrap multiple documents in a shared root or split the stream and parse each document with its own reader.","If the source is concatenated documents, split on each <?xml declaration or on the known root tags and parse the parts separately.","Pre-validate the stream with a standard STAX parser so multiple-root input fails early with clear context."],"exampleFix":"// before: one InputStream holding two concatenated pom documents\nreader.read(in, true); // throws Duplicated tag: 'project' at the second root\n\n// after: split documents, parse each with its own reader\nfor (byte[] doc : splitXmlDocuments(in)) {\n    Model model = reader.read(new ByteArrayInputStream(doc), true);\n}","handlingStrategy":"try-catch","validationCode":"// Fail fast on multi-root streams before calling the model reader\nXMLInputFactory f = XMLInputFactory.newFactory();\nf.setProperty(XMLInputFactory.SUPPORT_DTD, false);\nXMLStreamReader p = f.createXMLStreamReader(new ByteArrayInputStream(bytes));\ntry {\n    int roots = 0;\n    while (p.hasNext()) {\n        if (p.next() == XMLStreamReader.START_ELEMENT && ++roots > 1) {\n            throw new IllegalStateException(\"Input has more than one root element\");\n        }\n    }\n} finally {\n    p.close();\n}","typeGuard":null,"tryCatchPattern":"try {\n    Model model = reader.read(parser, true);\n} catch (XMLStreamException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Duplicated tag\")) {\n        // stream carried a second top-level element: fix the producer or split documents\n    }\n    throw e;\n}","preventionTips":["Never concatenate XML documents into a single stream; split or wrap them.","Wrap multi-document batches in one container element and parse the children individually.","Run a well-formedness check before model parsing in ingestion pipelines."],"tags":["xml","stax","malformed-input","root-element","parsing"],"backgroundTag":"xml-multiple-root-elements","analyzedSha":"e4093d4e120eac99d6bdce5ba67cace2f3085c97","analyzedAt":"2026-08-21T22:58:24.034Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}