{"record":{"id":"6ed15b79f2e1c035","repo":"angular/components","slug":"matbadge-must-be-attached-to-an-element-node","errorCode":null,"errorMessage":"matBadge must be attached to an element node.","messagePattern":"matBadge must be attached to an element node\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/material/badge/badge.ts","lineNumber":184,"sourceCode":"\n  private _document = inject(DOCUMENT);\n\n  constructor() {\n    const config = inject(MAT_BADGE_CONFIG, {optional: true});\n    const styleLoader = inject(_CdkPrivateStyleLoader);\n    styleLoader.load(_MatBadgeStyleLoader);\n    styleLoader.load(_VisuallyHiddenLoader);\n\n    this._color = config?.color || 'primary';\n    this.overlap = config?.overlap ?? true;\n    this.position = config?.position || 'above after';\n    this.size = config?.size || 'medium';\n\n    if (typeof ngDevMode === 'undefined' || ngDevMode) {\n      const nativeElement = this._elementRef.nativeElement;\n\n      if (nativeElement.nodeType !== nativeElement.ELEMENT_NODE) {\n        throw Error('matBadge must be attached to an element node.');\n      }\n    }\n  }\n\n  /** Whether the badge is above the host or not */\n  isAbove(): boolean {\n    return this.position.indexOf('below') === -1;\n  }\n\n  /** Whether the badge is after the host or not */\n  isAfter(): boolean {\n    return this.position.indexOf('before') === -1;\n  }\n\n  /**\n   * Gets the element into which the badge's content is being rendered. Undefined if the element\n   * hasn't been created (e.g. if the badge doesn't have content).\n   */","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/angular/components/blob/0411926e7d8ae06b32236ec1048a888cfad5abf2/src/material/badge/badge.ts#L166-L202","documentation":"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).","triggerScenarios":"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.","commonSituations":"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).","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)."],"exampleFix":"// before\n<ng-container matBadge=\"3\">Items</ng-container>\n// after\n<span matBadge=\"3\">Items</span>","handlingStrategy":"validation","validationCode":"// before applying the directive, ensure the target is a real element\nconst el = document.querySelector('.toolbar-title');\nif (!el || el.nodeType !== Node.ELEMENT_NODE) {\n  throw new Error('matBadge target must be an element node');\n}","typeGuard":"function isElementNode(n: Node): n is HTMLElement {\n  return n.nodeType === Node.ELEMENT_NODE;\n}","tryCatchPattern":"try {\n  renderTemplate(); // template with matBadge\n} catch (e) {\n  if (e instanceof Error && e.message.includes('matBadge must be attached to an element node')) {\n    logger.warn('matBadge applied to non-element node; fix template');\n  } else { throw e; }\n}","preventionTips":["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."],"tags":["angular-material","badge","dom-node","dev-mode"],"backgroundTag":"directive-requires-element-node","analyzedSha":"0411926e7d8ae06b32236ec1048a888cfad5abf2","analyzedAt":"2026-08-31T11:58:23.400Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}