angular/components · error · SchematicsException
Cannot determine child element indentation because the speci
Error message
Cannot determine child element indentation because the specified Parse5 element does not have any source code location metadata.
What it means
getChildElementIndentation in src/cdk/schematics/utils/parse5-element.ts measures the column of a child element to compute indentation when inserting markup into HTML. Parse5 only provides sourceCodeLocation metadata when the document is parsed with location info enabled. If neither the child element nor the given element carries sourceCodeLocation, the function cannot compute indentation and throws this SchematicsException.
Source
Thrown at src/cdk/schematics/utils/parse5-element.ts:22
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import {SchematicsException} from '@angular-devkit/schematics';
import {DefaultTreeAdapterMap} from 'parse5';
// At the time of writing `parse5` doesn't expose the node interfaces directly, even though
// they're used as return types, but We can still access them through `DefaultTreeAdapterMap`.
export type Element = DefaultTreeAdapterMap['element'];
export type ChildNode = DefaultTreeAdapterMap['childNode'];
/** Determines the indentation of child elements for the given Parse5 element. */
export function getChildElementIndentation(element: Element) {
const childElement = element.childNodes.find(node => (node as Element).tagName) as Element | null;
if ((childElement && !childElement.sourceCodeLocation) || !element.sourceCodeLocation) {
throw new SchematicsException(
'Cannot determine child element indentation because the ' +
'specified Parse5 element does not have any source code location metadata.',
);
}
const startColumns = childElement
? // In case there are child elements inside of the element, we assume that their
// indentation is also applicable for other child elements.
childElement.sourceCodeLocation!.startCol
: // In case there is no child element, we just assume that child elements should be indented
// by two spaces.
element.sourceCodeLocation!.startCol + 2;
// Since Parse5 does not set the `startCol` properties as zero-based, we need to subtract
// one column in order to have a proper zero-based offset for the indentation.
return startColumns - 1;
}
View on GitHub (pinned to 0411926e7d)
Solutions
- Parse the HTML with location info enabled (default html.parse / parse5 with sourceCodeLocationInfo: true) before passing elements to getChildElementIndentation.
- Pass elements obtained directly from a freshly parsed document, not programmatically created or deeply cloned nodes.
- If you control the caller, fall back to a default indentation (e.g. 2 or 4 spaces) when sourceCodeLocation is unavailable instead of calling the utility.
- Avoid round-tripping the HTML through serialize/parse cycles before indentation computation, which can strip location metadata.
Example fix
// before
const html = parse5.parse(fs.readFileSync('index.html', 'utf8'), { treeAdapter: customAdapter });
// after
const html = parse5.parse(fs.readFileSync('index.html', 'utf8'), { sourceCodeLocationInfo: true }); Defensive patterns
Strategy: type-guard
Validate before calling
const doc = parse5.parse(html, { sourceCodeLocationInfo: true });
if (!doc.sourceCodeLocation) throw new Error('Parse5 tree lacks source code locations; re-parse with sourceCodeLocationInfo: true'); Type guard
function hasSourceCodeLocation(el: parse5.Element): el is parse5.Element & { sourceCodeLocation: parse5.ElementLocation } {
return !!el.sourceCodeLocation && el.childNodes.some(n => 'tagName' in n && !!(n as parse5.Element).sourceCodeLocation);
} Try / catch
try {
const indent = getChildElementIndentation(head);
} catch (e) {
if (String(e.message).includes('source code location metadata')) {
const indent = ' '; // fallback to 2-space indentation
} else throw e;
} Prevention
- Always parse HTML with parse5's sourceCodeLocationInfo enabled when indentation utilities will run on the tree.
- Never feed programmatically constructed or serialized-and-reparsed nodes into indentation helpers.
- Write schematic unit tests that assert location metadata exists on the parsed fixture.
When it happens
Trigger: A schematic (e.g. addHtmlElementToBody/head flows that compute indentation via indentationOffset) parses index.html whose resulting Parse5 Element has no sourceCodeLocation — typically because the tree was built without location info or produced programmatically rather than parsed from source text.
Common situations: Mostly hit by developers writing or extending schematics that reuse these utilities: constructing Parse5 nodes manually, parsing with treeAdapter/parsing options that omit location info, or feeding already-transformed (serialized/re-parsed) HTML through the utility.
Related errors
- Cannot read "${filePath}" because it does not exist.
- No data could be found for target version: ${version}
- Could not find file for path: ${path}
- Module not found: ${modulePath}
- Could not read Angular module file: ${modulePath}
AI-assisted analysis of angular/components@0411926e7d (2026-08-31).
Data as JSON: /api/errors/69777c4ce8564589.
Report an issue: GitHub.