{"record":{"id":"fd032fee858c51e3","repo":"angular/components","slug":"name-must-be-attached-to-an-element-node-curre","errorCode":null,"errorMessage":"${name} must be attached to an element node. Currently attached to \"${node.nodeName}\".","messagePattern":"(.+?) must be attached to an element node\\. Currently attached to \"(.+?)\"\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cdk/drag-drop/directives/assertions.ts","lineNumber":16,"sourceCode":"/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\n/**\n * Asserts that a particular node is an element.\n * @param node Node to be checked.\n * @param name Name to attach to the error message.\n */\nexport function assertElementNode(node: Node, name: string): asserts node is HTMLElement {\n  if (node.nodeType !== 1) {\n    throw Error(\n      `${name} must be attached to an element node. ` + `Currently attached to \"${node.nodeName}\".`,\n    );\n  }\n}\n","sourceCodeStart":1,"sourceCodeEnd":21,"githubUrl":"https://github.com/angular/components/blob/0411926e7d8ae06b32236ec1048a888cfad5abf2/src/cdk/drag-drop/directives/assertions.ts#L1-L21","documentation":"CdkDrag and CdkDropList must be applied to an HTMLElement. assertElementNode validates the host node of the directive and throws when the directive lands on a non-element node (nodeType !== 1), such as a text node or comment node. This typically happens through structural-DOM surprises rather than direct misuse.","triggerScenarios":"cdkDrag or cdkDropList placed on an element that Angular renders as a comment node (e.g. an <ng-container> host), or attached to something whose root becomes a text node; _updateRootElement re-runs the assertion when the root element changes and the new node is not an element.","commonSituations":"Putting cdkDrag on <ng-container *ngIf=...>; template conditions leaving only a comment placeholder; wrapping cdkDrag in a structural directive that swaps the host node.","solutions":["Move cdkDrag/cdkDropList onto a real element like a <div>, <li>, or <tr>.","Replace <ng-container cdkDrag> with a concrete element that carries the directive.","If the root can change at runtime, ensure the node bound via cdkDragRootElement / cdkDropListRootElement matches a single HTMLElement, not text/comment nodes.","Inspect the DOM in devtools: the element with the directive must appear as a tag, not a `<!-- -->` comment."],"exampleFix":"// before\n<ng-container cdkDrag *ngIf=\"item\">...</ng-container>\n// after\n<div cdkDrag *ngIf=\"item\">...</div>","handlingStrategy":"type-guard","validationCode":"const el = document.querySelector('[cdkDrag]');\nif (el && el.nodeType !== 1) {\n  throw new Error('cdkDrag host must be an element node');\n}","typeGuard":"function isElementNode(node: Node): node is HTMLElement {\n  return node.nodeType === 1;\n}","tryCatchPattern":"try {\n  dragRef.setRootElement(someNode);\n} catch (e) {\n  if ((e as Error).message.includes('must be attached to an element node')) {\n    console.warn('Provide a real HTMLElement host for cdkDrag');\n  } else { throw e; }\n}","preventionTips":["Never put cdkDrag/cdkDropList on <ng-container>.","Verify the directive host renders as a tag in devtools, not a comment node.","Use cdkDragRootElement with a selector that matches a real element.","Test drag setups with structural directives (*ngIf, *ngFor) on wrapper elements."],"tags":["angular","cdk","drag-drop","directive-host"],"backgroundTag":"invalid-host-element","analyzedSha":"0411926e7d8ae06b32236ec1048a888cfad5abf2","analyzedAt":"2026-08-31T11:58:23.400Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}