angular/components · error
<svg> tag not found
Error message
<svg> tag not found
What it means
MatIconRegistry._svgElementFromString parses an SVG literal string by assigning it to a DIV's innerHTML and querying for an 'svg' element. If the string contains no <svg> tag at its root, the registry cannot produce an icon element and throws. This is a guard against malformed icon literals registered via addSvgIconLiteral or addSvgIconLiteralInNamespace.
Source
Thrown at src/material/icon/icon-registry.ts:579
// http://stackoverflow.com/questions/23003278/svg-innerhtml-in-firefox-can-not-display
const svg = this._svgElementFromString(trustedHTMLFromString('<svg></svg>'));
// Clone the node so we don't remove it from the parent icon set element.
svg.appendChild(iconElement);
return this._setSvgAttributes(svg, options);
}
/**
* Creates a DOM element from the given SVG string.
*/
private _svgElementFromString(str: TrustedHTML): SVGElement {
const div = this._document.createElement('DIV');
div.innerHTML = str as unknown as string;
const svg = div.querySelector('svg') as SVGElement;
// TODO: add an ngDevMode check
if (!svg) {
throw Error('<svg> tag not found');
}
return svg;
}
/**
* Converts an element into an SVG node by cloning all of its children.
*/
private _toSvgElement(element: Element): SVGElement {
const svg = this._svgElementFromString(trustedHTMLFromString('<svg></svg>'));
const attributes = element.attributes;
// Copy over all the attributes from the `symbol` to the new SVG, except the id.
for (let i = 0; i < attributes.length; i++) {
const {name, value} = attributes[i];
if (name !== 'id') {
svg.setAttribute(name, value);View on GitHub (pinned to 0411926e7d)
Solutions
- Wrap the literal in a root <svg> element including the xmlns attribute: <svg xmlns="http://www.w3.org/2000/svg" viewBox="...">...</svg>
- Verify the string actually contains '<svg' before registering (log it in dev).
- If you meant to load from a URL/file, use addSvgIcon(name, sanitizer.bypassSecurityTrustResourceUrl(url)) instead of the literal variant.
Example fix
// before
registry.addSvgIconLiteral('star', '<path d="M3 3h18v18H3z"/>');
// after
registry.addSvgIconLiteral('star', '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 3h18v18H3z"/></svg>'); Defensive patterns
Strategy: validation
Validate before calling
function isSvgLiteral(str: string): boolean {
return typeof str === 'string' && /<svg[\s>]/i.test(str.trim());
}
if (!isSvgLiteral(svgMarkup)) {
throw new Error('Icon literal must contain a root <svg> element');
}
registry.addSvgIconLiteral('star', svgMarkup); Type guard
function hasRootSvg(str: unknown): str is string {
return typeof str === 'string' && new DOMParser()
.parseFromString(str, 'image/svg+xml')
.querySelector('svg') !== null;
} Try / catch
try {
registry.addSvgIconLiteral(name, markup);
} catch (e) {
if ((e as Error).message.includes('<svg> tag not found')) {
console.warn(`Skipping icon "${name}": markup has no <svg> root`);
} else { throw e; }
} Prevention
- Always copy the full <svg>...</svg> element, never just its inner markup
- Include xmlns="http://www.w3.org/2000/svg" on the root svg tag
- Add a build-time lint/unit test asserting every registered literal starts with <svg
When it happens
Trigger: Calling registry.addSvgIconLiteral(name, html) or addSvgIconLiteralInNamespace(ns, name, html) with a string whose root is not an <svg> element (e.g. a <path>, <img>, empty string, or HTML wrapper).
Common situations: Copying an SVG path's inner markup instead of the whole <svg>...</svg> element; build pipelines that strip the svg tag; passing an asset URL string instead of inline SVG markup.
Related errors
- The literal provided to MatIconRegistry was not trusted as s
- The URL provided to MatIconRegistry was not trusted as a res
- Unable to find icon with the name "${name}"
- Cannot fetch icon from URL "${safeUrl}".
- mat-tab-group background color must be set through the Sass
AI-assisted analysis of angular/components@0411926e7d (2026-08-31).
Data as JSON: /api/errors/f6e30b2828e568d3.
Report an issue: GitHub.