angular/angular · warning
The XML file does not contain a <${rootNodeName}> root node.
Error message
The XML file does not contain a <${rootNodeName}> root node. What it means
`canParseXml()` - shared by the XLIFF 1.2, XLIFF 2.0, and XTB parsers - parsed the file as XML without ERROR-level problems, but found no root element with the expected name (`xliff`, `xliffv2`, or `translationbundle`). It returns canParse=false with this warning so the loader can attempt the next parser.
Source
Thrown at packages/localize/tools/src/translate/translation_files/translation_parsers/translation_utils.ts:113
rootNodeName: string,
attributes: Record<string, string>,
): ParseAnalysis<XmlTranslationParserHint> {
const diagnostics = new Diagnostics();
const xmlParser = new XmlParser();
const xml = xmlParser.parse(contents, filePath);
if (
xml.rootNodes.length === 0 ||
xml.errors.some((error) => error.level === ParseErrorLevel.ERROR)
) {
xml.errors.forEach((e) => addParseError(diagnostics, e));
return {canParse: false, diagnostics};
}
const rootElements = xml.rootNodes.filter(isNamedElement(rootNodeName));
const rootElement = rootElements[0];
if (rootElement === undefined) {
diagnostics.warn(`The XML file does not contain a <${rootNodeName}> root node.`);
return {canParse: false, diagnostics};
}
for (const attrKey of Object.keys(attributes)) {
const attr = rootElement.attrs.find((attr) => attr.name === attrKey);
if (attr === undefined || attr.value !== attributes[attrKey]) {
addParseDiagnostic(
diagnostics,
rootElement.sourceSpan,
`The <${rootNodeName}> node does not have the required attribute: ${attrKey}="${attributes[attrKey]}".`,
ParseErrorLevel.WARNING,
);
return {canParse: false, diagnostics};
}
}
if (rootElements.length > 1) {
xml.errors.push(View on GitHub (pinned to 51cb07e980)
Solutions
- Open the file and check the actual root element and its version attribute (e.g. `<xliff version="1.2">` vs `<xliff version="2.0" xmlns="urn:oasis:names:tc:xliff:document:2.0">`).
- Regenerate the file with the serializer format that matches the file you intend to use (`ng extract-i18n --format=xlf|xlf2|xtb`).
- Keep the translate step's parser expectations aligned with the extraction format in one place (shared config).
Example fix
// before: declared XLIFF 1.2 flow, file is actually XLIFF 2.0 <xliff version="2.0" xmlns="urn:oasis:names:tc:xliff:document:2.0">...</xliff> // after: match versions - use XLIFF 1.2 <xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">...</xliff> // (or switch the whole pipeline to --format=xlf2)
Defensive patterns
Strategy: validation
Validate before calling
// Verify the XML root element matches the expected format before loading
function hasXmlRoot(contents: string, rootName: string): boolean {
const match = contents.match(/^\s*<\?xml[^>]*\?>\s*<(?<root>[a-zA-Z0-9:_.-]+)/);
return match?.groups?.root === rootName;
}
// XLIFF 1.2 root: 'xliff' with version="1.2"; XLIFF 2.0: 'xliff' version="2.0"; XTB: 'translationbundle'
if (!hasXmlRoot(contents, 'xliff')) throw new Error(`Unexpected root element in ${filePath}`); Prevention
- Keep the extraction format and the translation-file format in one shared config value.
- Check the root element's version attribute when files come back from vendors.
When it happens
Trigger: Passing an XML translation file whose root element does not match the format the parser expects: an XLIFF 2.0 file when the XLIFF 1.2 parser inspects it (or vice versa), an XTB file inspected by an XLIFF parser, or any XML doc with a different root.
Common situations: Mixing XLIFF versions between what the extraction produced and what translation was configured for; a vendor/tool exporting a wrapper XML; manually restructured files.
Related errors
- xliff parse errors: ${errors.join(' ')}
- FETCH_UPLOAD_PROGRESS_NOT_SUPPORTED
- FETCH_RESPONSE_BODY_TOO_LARGE
- xliff2 parse errors: ${errors.join(' ')}
- The provided locale "${providedLocale}" does not match the t
AI-assisted analysis of angular/angular@51cb07e980 (2026-08-22).
Data as JSON: /api/errors/465247cb50cc1dfb.
Report an issue: GitHub.