angular/components · error · Error

Invalid DOM structure for drop list. Alternate container ele

Error message

Invalid DOM structure for drop list. Alternate container element must be a descendant of the drop list.

What it means

withElementContainer lets a CdkDropListRef use an alternate container element for its drag items. As a dev-mode structural check, the container must either be the drop list element itself or a descendant of it; otherwise scrolling/bounds logic breaks, so the ref throws.

Source

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

   * Configures the drop list so that a different element is used as the container for the
   * dragged items. This is useful for the cases when one might not have control over the
   * full DOM that sets up the dragging.
   * Note that the alternate container needs to be a descendant of the drop list.
   * @param container New element container to be assigned.
   */
  withElementContainer(container: HTMLElement): this {
    if (container === this._container) {
      return this;
    }

    const element = coerceElement(this.element);

    if (
      (typeof ngDevMode === 'undefined' || ngDevMode) &&
      container !== element &&
      !element.contains(container)
    ) {
      throw new Error(
        'Invalid DOM structure for drop list. Alternate container element must be a descendant of the drop list.',
      );
    }

    const oldContainerIndex = this._scrollableElements.indexOf(this._container);
    const newContainerIndex = this._scrollableElements.indexOf(container);

    if (oldContainerIndex > -1) {
      this._scrollableElements.splice(oldContainerIndex, 1);
    }

    if (newContainerIndex > -1) {
      this._scrollableElements.splice(newContainerIndex, 1);
    }

    if (this._sortStrategy) {
      this._sortStrategy.withElementContainer(container);
    }

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Move the alternate container element so it is a descendant of the cdkDropList element (or is the element itself).
  2. Ensure elementContainerSelector matches only descendants of the drop list host.
  3. If the container must live elsewhere, restructure so the drop list host wraps it.
  4. Drop the alternate container usage entirely and keep items as direct children of cdkDropList.

Example fix

// before
<div class="wrapper">
  <div cdkDropList #list></div>
  <div class="container">items...</div>
</div>
list.withElementContainer(container); // sibling -> throws
// after
<div cdkDropList #list>
  <div class="container">items...</div>
</div>
list.withElementContainer(container); // descendant -> ok
Defensive patterns

Strategy: validation

Validate before calling

const el = dropListEl.nativeElement;
if (container !== el && !el.contains(container)) {
  throw new Error('Alternate container must be a descendant of the drop list');
}

Try / catch

try {
  ref.withElementContainer(container);
} catch (e) {
  if ((e as Error).message.includes('must be a descendant of the drop list')) {
    ref.withElementContainer(dropListEl.nativeElement);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling dropListRef.withElementContainer(el) (directly or via elementContainerSelector resolution) with an element that is not the drop list element and is not contained within it — e.g. a sibling, a parent, or an element in another part of the DOM.

Common situations: Moving the alternate container outside the drop list during a refactor; passing document.body or a shared overlay container; selector resolving to an element outside the host after DOM restructuring.

Related errors


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