angular/components · error · Error
matBadge must be attached to an element node.
Error message
matBadge must be attached to an element node.
What it means
MatBadge is a directive that renders a badge overlay positioned relative to its host element via CSS. It requires _elementRef.nativeElement to be a real DOM element node so it can append the badge element to it. In ngDevMode it throws if the host node is not an ELEMENT_NODE (e.g. a text, comment, or document node).
Source
Thrown at src/material/badge/badge.ts:184
private _document = inject(DOCUMENT);
constructor() {
const config = inject(MAT_BADGE_CONFIG, {optional: true});
const styleLoader = inject(_CdkPrivateStyleLoader);
styleLoader.load(_MatBadgeStyleLoader);
styleLoader.load(_VisuallyHiddenLoader);
this._color = config?.color || 'primary';
this.overlap = config?.overlap ?? true;
this.position = config?.position || 'above after';
this.size = config?.size || 'medium';
if (typeof ngDevMode === 'undefined' || ngDevMode) {
const nativeElement = this._elementRef.nativeElement;
if (nativeElement.nodeType !== nativeElement.ELEMENT_NODE) {
throw Error('matBadge must be attached to an element node.');
}
}
}
/** Whether the badge is above the host or not */
isAbove(): boolean {
return this.position.indexOf('below') === -1;
}
/** Whether the badge is after the host or not */
isAfter(): boolean {
return this.position.indexOf('before') === -1;
}
/**
* Gets the element into which the badge's content is being rendered. Undefined if the element
* hasn't been created (e.g. if the badge doesn't have content).
*/View on GitHub (pinned to 0411926e7d)
Solutions
- Move matBadge to a real HTML element (div, span, button, mat-icon, etc.).
- If wrapping ng-container content, add a wrapper element and put matBadge on it.
- Ensure the element the directive is on actually renders an element node in the DOM (not a template/comment placeholder).
Example fix
// before <ng-container matBadge="3">Items</ng-container> // after <span matBadge="3">Items</span>
Defensive patterns
Strategy: validation
Validate before calling
// before applying the directive, ensure the target is a real element
const el = document.querySelector('.toolbar-title');
if (!el || el.nodeType !== Node.ELEMENT_NODE) {
throw new Error('matBadge target must be an element node');
} Type guard
function isElementNode(n: Node): n is HTMLElement {
return n.nodeType === Node.ELEMENT_NODE;
} Try / catch
try {
renderTemplate(); // template with matBadge
} catch (e) {
if (e instanceof Error && e.message.includes('matBadge must be attached to an element node')) {
logger.warn('matBadge applied to non-element node; fix template');
} else { throw e; }
} Prevention
- Never put matBadge on ng-container or ng-template.
- Wrap template fragments in a real element when a badge is needed.
- Run dev-mode builds in CI so ngDevMode assertions catch bad templates.
When it happens
Trigger: Applying matBadge to something that produces a non-element node as the directive host — e.g. placing matBadge on <ng-container> or an attribute-style usage that resolves to a comment/text node.
Common situations: Developers try to hang a badge on ng-container, ng-template, or an SVG/text node; or a structural wrapper makes the directive host a comment node. Also common when porting templates from component selectors that render as comments (e.g. router-outlet-like placeholders).
Related errors
- A mat-tab-nav-panel must be specified via [tabPanel].
- Cannot specify both the `options` and `interval` inputs at t
- Value of `options` input cannot be an empty array
- MatTimepicker can only be registered with one input at a tim
- mat-grid-list: must pass in number of columns. Example: <mat
AI-assisted analysis of angular/components@0411926e7d (2026-08-31).
Data as JSON: /api/errors/6ed15b79f2e1c035.
Report an issue: GitHub.