angular/components · error

Host already has a portal attached

Error message

Host already has a portal attached

What it means

BasePortalOutlet.attach calls `throwPortalAlreadyAttachedError` when `_attachedPortal` is already set — one outlet can hold only one portal at a time. You must detach the current portal before attaching a new one.

Source

Thrown at src/cdk/portal/portal-errors.ts:22

 *
 * 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
 */

/**
 * Throws an exception when attempting to attach a null portal to a host.
 * @docs-private
 */
export function throwNullPortalError() {
  throw Error('Must provide a portal to attach');
}

/**
 * Throws an exception when attempting to attach a portal to a host that is already attached.
 * @docs-private
 */
export function throwPortalAlreadyAttachedError() {
  throw Error('Host already has a portal attached');
}

/**
 * Throws an exception when attempting to attach a portal to an already-disposed host.
 * @docs-private
 */
export function throwPortalOutletAlreadyDisposedError() {
  throw Error('This PortalOutlet has already been disposed');
}

/**
 * Throws an exception when attempting to attach an unknown portal type.
 * @docs-private
 */
export function throwUnknownPortalTypeError() {
  throw Error(
    'Attempting to attach an unknown Portal type. BasePortalOutlet accepts either ' +
      'a ComponentPortal or a TemplatePortal.',

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Call `outlet.detach()` before `outlet.attach(newPortal)`
  2. Track attached state and skip attach if the same portal is already attached
  3. Use `hasAttached()` to check before attaching
  4. In components, detach in ngOnDestroy and before re-attachment on input changes

Example fix

// before
this.outlet.attach(portal);
// ...later
this.outlet.attach(otherPortal); // throws
// after
if (this.outlet.hasAttached()) { this.outlet.detach(); }
this.outlet.attach(otherPortal);
Defensive patterns

Strategy: try-catch

Validate before calling

if (!outlet.hasAttached()) outlet.attach(portal);

Try / catch

try { outlet.attach(portal); } catch (e) { if (String(e.message).includes('already has a portal attached')) outlet.detach(); outlet.attach(portal); } else { throw e; } }

Prevention

When it happens

Trigger: Calling `attach` twice on the same outlet without `detach()`; attaching from both an @Input setter and a lifecycle hook; multiple components writing to a shared `<ng-template cdkPortalOutlet>`.

Common situations: Reactive updates that re-trigger attach on every emission without detaching; two directives/components competing for the same outlet; rapid state changes (typing, routing) that call attach repeatedly.

Related errors


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