angular/components · error
DOM portal content must be attached to a parent node.
Error message
DOM portal content must be attached to a parent node.
What it means
Same check as DomPortalOutlet, but in the CdkPortalOutlet directive: a DomPortal's element must have a parentNode when `attachDomPortal` runs, since the outlet uses an anchor comment to restore the element's original DOM position on detach.
Source
Thrown at src/cdk/portal/portal-directives.ts:182
super.setDisposeFn(() => this._viewContainerRef.clear());
this._attachedPortal = portal;
this._attachedRef = viewRef;
this.attached.emit(viewRef);
return viewRef;
}
/**
* Attaches the given DomPortal to this PortalHost by moving all of the portal content into it.
* @param portal Portal to be attached.
* @deprecated To be turned into a method.
* @breaking-change 10.0.0
*/
override attachDomPortal = (portal: DomPortal) => {
const element = portal.element;
if (!element.parentNode && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw Error('DOM portal content must be attached to a parent node.');
}
// Anchor used to save the element's previous position so
// that we can restore it when the portal is detached.
const anchorNode = this._document.createComment('dom-portal');
portal.setAttachedHost(this);
element.parentNode!.insertBefore(anchorNode, element);
this._getRootNode().appendChild(element);
this._attachedPortal = portal;
super.setDisposeFn(() => {
if (anchorNode.parentNode) {
anchorNode.parentNode!.replaceChild(element, anchorNode);
}
});
};
View on GitHub (pinned to 0411926e7d)
Solutions
- Ensure the source element is inserted in the DOM before constructing the DomPortal
- Attach the portal only after view init (ngAfterViewInit) when the element is in the tree
- Switch to TemplatePortal/ComponentPortal for non-DOM-hosted content
- Add an `el.isConnected` guard before calling attach
Example fix
// before
const portal = new DomPortal(this.detachedDiv);
this.outlet.attach(portal); // throws
// after
ngAfterViewInit() {
if (!this.detachedDiv.parentNode) { this.hostRef.nativeElement.appendChild(this.detachedDiv); }
this.outlet.attach(new DomPortal(this.detachedDiv));
} Defensive patterns
Strategy: validation
Validate before calling
ngAfterViewInit() {
if (this.sourceEl?.isConnected && this.outlet && !this.outlet.hasAttached()) {
this.outlet.attach(new DomPortal(this.sourceEl));
}
} Type guard
function isAttachedToDom(el: Node | null | undefined): el is Node {
return !!el && el.isConnected && el.parentNode != null;
} Try / catch
try {
outlet.attachDomPortal(portal);
} catch (e) {
if (e.message.includes('must be attached to a parent node')) {
outlet._document.body.appendChild(portal.element);
outlet.attachDomPortal(portal);
} else { throw e; }
} Prevention
- Attach DOM portals only after view init when nodes are in the tree
- Verify parentNode exists before calling attach
- Avoid binding detached nodes to cdkPortalOutlet inputs
- Use TemplatePortal when the content originates from Angular templates
When it happens
Trigger: Binding an element without a parent to a `<ng-template cdkPortalOutlet>` via a DomPortal, e.g. `outlet.attach(new DomPortal(detachedEl))`, including elements created in component code or parsed from strings.
Common situations: Angular app rendering detached elements created with renderer.createElement; passing content extracted from a detached template; host bindings that clear the element's parent before the portal attaches; SSR/hydration edge cases where the node is not yet in the tree.
Related errors
- DOM portal content must be attached to a parent node.
- Cannot attach component portal to outlet without an Applicat
- Must provide a portal to attach
- Host already has a portal attached
- This PortalOutlet has already been disposed
AI-assisted analysis of angular/components@0411926e7d (2026-08-31).
Data as JSON: /api/errors/e05160ff71532907.
Report an issue: GitHub.