angular/components · error · Error

Invalid DOM structure for drop list. All items must be place

Error message

Invalid DOM structure for drop list. All items must be placed directly inside of the element container.

What it means

When a drop list uses an alternate element container, every drag item's visible element must be a direct child of that container so positioning and collision logic work. The check runs once dragging starts (dev mode only, and only when an alternate container is in use); any item whose visible element's parent isn't the container triggers this error.

Source

Thrown at src/cdk/drag-drop/drop-list-ref.ts:607

  _stopScrolling() {
    this._stopScrollTimers.next();
  }

  /** Starts the dragging sequence within the list. */
  private _draggingStarted() {
    const styles = this._container.style as DragCSSStyleDeclaration;
    this.beforeStarted.next();
    this._isDragging = true;

    if (
      (typeof ngDevMode === 'undefined' || ngDevMode) &&
      // Prevent the check from running on apps not using an alternate container. Ideally we
      // would always run it, but introducing it at this stage would be a breaking change.
      this._container !== coerceElement(this.element)
    ) {
      for (const drag of this._draggables) {
        if (!drag.isDragging() && drag.getVisibleElement().parentNode !== this._container) {
          throw new Error(
            'Invalid DOM structure for drop list. All items must be placed directly inside of the element container.',
          );
        }
      }
    }

    // We need to disable scroll snapping while the user is dragging, because it breaks automatic
    // scrolling. The browser seems to round the value based on the snapping points which means
    // that we can't increment/decrement the scroll position.
    this._initialScrollSnap = styles.msScrollSnapType || styles.scrollSnapType || '';
    styles.scrollSnapType = styles.msScrollSnapType = 'none';
    this._sortStrategy.start(this._draggables);
    this._cacheParentPositions();
    this._viewportScrollSubscription.unsubscribe();
    this._listenToScrollEvents();
  }

  /** Caches the positions of the configured scrollable parents. */

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Make each cdkDrag item's element a direct child of the element container — remove intermediate wrapper elements.
  2. Point elementContainerSelector at the actual direct parent of the items (e.g. the wrapper you cannot remove).
  3. Move structural directives (e.g. ngFor with wrapper) so the cdkDrag host is the container's direct child.
  4. If you don't need the alternate container, remove elementContainerSelector so the check is skipped.

Example fix

// before
<div cdkDropList elementContainerSelector=".list">
  <div class="list">
    <div class="row"><div cdkDrag>Item</div></div>
  </div>
</div>
// after
<div cdkDropList elementContainerSelector=".list">
  <div class="list">
    <div cdkDrag>Item</div>
  </div>
</div>
Defensive patterns

Strategy: validation

Validate before calling

const items = Array.from(document.querySelectorAll('cdk-drag'));
const bad = items.filter(el => el.getVisibleElement?.().parentNode !== container);
if (bad.length) throw new Error('Some drag items are not direct children of the container');

Try / catch

try {
  dragRef.start(event);
} catch (e) {
  if ((e as Error).message.includes('directly inside of the element container')) {
    console.error('Remove wrappers around cdkDrag items or fix elementContainerSelector');
  } else throw e;
}

Prevention

When it happens

Trigger: Dragging starts (via start() or an item entering the list) while at least one non-dragging cdkDrag item's rendered element is nested inside an intermediary wrapper instead of directly inside the element container.

Common situations: Wrapping cdkDrag items in a <div class="row"> or ng-container-rendered wrapper while also setting elementContainerSelector; items rendered into a different parent by a structural directive; virtual-scroll moving items out of the container.

Related errors


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