angular/components · error · Error

${name} must be attached to an element node. Currently attac

Error message

${name} must be attached to an element node. Currently attached to "${node.nodeName}".

What it means

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.

Source

Thrown at src/cdk/drag-drop/directives/assertions.ts:16

/**
 * @license
 * Copyright Google LLC All Rights Reserved.
 *
 * 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
 */

/**
 * Asserts that a particular node is an element.
 * @param node Node to be checked.
 * @param name Name to attach to the error message.
 */
export function assertElementNode(node: Node, name: string): asserts node is HTMLElement {
  if (node.nodeType !== 1) {
    throw Error(
      `${name} must be attached to an element node. ` + `Currently attached to "${node.nodeName}".`,
    );
  }
}

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Move cdkDrag/cdkDropList onto a real element like a <div>, <li>, or <tr>.
  2. Replace <ng-container cdkDrag> with a concrete element that carries the directive.
  3. If the root can change at runtime, ensure the node bound via cdkDragRootElement / cdkDropListRootElement matches a single HTMLElement, not text/comment nodes.
  4. Inspect the DOM in devtools: the element with the directive must appear as a tag, not a `<!-- -->` comment.

Example fix

// before
<ng-container cdkDrag *ngIf="item">...</ng-container>
// after
<div cdkDrag *ngIf="item">...</div>
Defensive patterns

Strategy: type-guard

Validate before calling

const el = document.querySelector('[cdkDrag]');
if (el && el.nodeType !== 1) {
  throw new Error('cdkDrag host must be an element node');
}

Type guard

function isElementNode(node: Node): node is HTMLElement {
  return node.nodeType === 1;
}

Try / catch

try {
  dragRef.setRootElement(someNode);
} catch (e) {
  if ((e as Error).message.includes('must be attached to an element node')) {
    console.warn('Provide a real HTMLElement host for cdkDrag');
  } else { throw e; }
}

Prevention

When it happens

Trigger: 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.

Common situations: Putting cdkDrag on <ng-container *ngIf=...>; template conditions leaving only a comment placeholder; wrapping cdkDrag in a structural directive that swaps the host node.

Related errors


AI-assisted analysis of angular/components@0411926e7d (2026-08-31). Data as JSON: /api/errors/fd032fee858c51e3. Report an issue: GitHub.