angular/components · error

This PortalOutlet has already been disposed

Error message

This PortalOutlet has already been disposed

What it means

`throwPortalOutletAlreadyDisposedError` fires when `attach` is called on an outlet whose `dispose()` has already run. A disposed outlet has torn down its resources and can never host a portal again; a new outlet instance is required.

Source

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

 */
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.',
  );
}

/**
 * Throws an exception when attempting to attach a portal to a null host.
 * @docs-private
 */
export function throwNullPortalOutletError() {

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Create a new outlet instance after dispose instead of reusing it
  2. Guard with a disposed flag/`isDisposed` check before attach
  3. Cancel pending async work (takeUntilDestroyed, unsubscribe) so attach never runs post-dispose
  4. Move outlet creation/dispose into the same component lifecycle as the attach logic

Example fix

// before
this.outlet.dispose();
this.outlet.attach(portal); // throws
// after
this.outlet.dispose();
this.outlet = new DomPortalOutlet(hostEl, injector, appRef, document);
this.outlet.attach(portal);
Defensive patterns

Strategy: try-catch

Validate before calling

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

Try / catch

try { outlet.attach(portal); } catch (e) { if (String(e.message).includes('already been disposed')) { outlet = createOutlet(); outlet.attach(portal); } else { throw e; } }

Prevention

When it happens

Trigger: Calling `attach` on a DomPortalOutlet after `outlet.dispose()`; using a cached/stored outlet reference after its host was destroyed; attaching a portal in a component whose outlet was disposed during teardown (e.g. after NavigationEnd cleanup).

Common situations: Long-lived services caching outlets for destroyed overlays; async callbacks (HTTP, timers) resolving after dispose; HMR or route changes disposing outlets while pending attaches are in flight.

Related errors


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