apache/maven · error · XMLStreamException
Duplicated tag: '${rootTag}'
Error message
Duplicated tag: '${rootTag}' What it means
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.
Source
Thrown at src/mdo/reader-stax.vm:279
*/
#if ( $locationTracking )
public ${root.name} read(XMLStreamReader parser, boolean strict, InputSource inputSrc) throws XMLStreamException {
#else
public ${root.name} read(XMLStreamReader parser, boolean strict) throws XMLStreamException {
#end
#if ( $needXmlContext )
Deque<Object> context = new ArrayDeque<>();
#end
$rootUcapName $rootLcapName = null;
int eventType = parser.getEventType();
boolean parsed = false;
while (eventType != XMLStreamReader.END_DOCUMENT) {
if (eventType == XMLStreamReader.START_ELEMENT) {
if (strict && ! "${rootTag}".equals(parser.getLocalName())) {
throw new XMLStreamException("Expected root element '${rootTag}' but found '" + parser.getName() + "'", parser.getLocation(), null);
} else if (parsed) {
// fallback, already expected a XMLStreamException due to invalid XML
throw new XMLStreamException("Duplicated tag: '${rootTag}'", parser.getLocation(), null);
}
#if ( $locationTracking )
$rootLcapName = parse${rootUcapName}(parser, strict, parser.getNamespaceURI(), inputSrc);
#elseif ( $needXmlContext )
$rootLcapName = parse${rootUcapName}(parser, strict, parser.getNamespaceURI(), context);
#else
$rootLcapName = parse${rootUcapName}(parser, strict, parser.getNamespaceURI());
#end
parsed = true;
}
eventType = parser.next();
}
if (parsed) {
return $rootLcapName;
}
throw new XMLStreamException("Expected root element '${rootTag}' but found no element at all: invalid XML document", parser.getLocation(), null);
} //-- ${root.name} read(XMLStreamReader, boolean)
View on GitHub (pinned to e4093d4e12)
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.
Example fix
// before: one InputStream holding two concatenated pom documents
reader.read(in, true); // throws Duplicated tag: 'project' at the second root
// after: split documents, parse each with its own reader
for (byte[] doc : splitXmlDocuments(in)) {
Model model = reader.read(new ByteArrayInputStream(doc), true);
} Defensive patterns
Strategy: try-catch
Validate before calling
// Fail fast on multi-root streams before calling the model reader
XMLInputFactory f = XMLInputFactory.newFactory();
f.setProperty(XMLInputFactory.SUPPORT_DTD, false);
XMLStreamReader p = f.createXMLStreamReader(new ByteArrayInputStream(bytes));
try {
int roots = 0;
while (p.hasNext()) {
if (p.next() == XMLStreamReader.START_ELEMENT && ++roots > 1) {
throw new IllegalStateException("Input has more than one root element");
}
}
} finally {
p.close();
} Try / catch
try {
Model model = reader.read(parser, true);
} catch (XMLStreamException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Duplicated tag")) {
// stream carried a second top-level element: fix the producer or split documents
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Duplicated tag: '${rootTag}'
- Expected root element '${rootTag}' but found '{}'
- Expected root element '${rootTag}' but found '{}'
- Expected root element '${rootTag}' but found no element at a
- Duplicated tag: '{}'
AI-assisted analysis of apache/maven@e4093d4e12 (2026-08-21).
Data as JSON: /api/errors/434b32cd06a51fe0.
Report an issue: GitHub.