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
- Make each cdkDrag item's element a direct child of the element container — remove intermediate wrapper elements.
- Point elementContainerSelector at the actual direct parent of the items (e.g. the wrapper you cannot remove).
- Move structural directives (e.g. ngFor with wrapper) so the cdkDrag host is the container's direct child.
- 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
- Keep cdkDrag elements as direct children of the element container.
- Align elementContainerSelector with the actual direct parent of the items.
- Re-check DOM structure after introducing wrappers, structural directives, or virtual scroll.
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
- Invalid DOM structure for drop list. Alternate container ele
- CdkDropList could not find an element container matching the
- ${name} must be attached to an element node. Currently attac
- Incorrect tree structure containing detached node.
- ListKeyManager constructed with a signal must receive an inj
AI-assisted analysis of angular/components@0411926e7d (2026-08-31).
Data as JSON: /api/errors/33f3aa30c494e5ba.
Report an issue: GitHub.