angular/components · error
Attempting to attach an unknown Portal type. BasePortalOutle
Error message
Attempting to attach an unknown Portal type. BasePortalOutlet accepts either a ComponentPortal or a TemplatePortal.
What it means
BasePortalOutlet.attach dispatches on portal type: ComponentPortal, TemplatePortal, or DomPortal. Anything else (or a malformed object) reaches the fallback `throwUnknownPortalTypeError`. It signals a wrong/incorrectly-typed argument rather than a runtime state issue.
Source
Thrown at src/cdk/portal/portal-errors.ts:38
*/
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() {
throw Error('Attempting to attach a portal to a null PortalOutlet');
}
/**
* Throws an exception when attempting to detach a portal that is not attached.
* @docs-private
*/
export function throwNoPortalAttachedError() {View on GitHub (pinned to 0411926e7d)
Solutions
- Pass a concrete `new ComponentPortal(MyComponent)` or `new TemplatePortal(templateRef, viewContainerRef)` instance
- Extend the correct Portal subclass for custom portals and keep the `_attachedHost`/type contract intact
- Remove incorrect casts (`as any`) hiding the type mismatch
- Update custom portal code when upgrading CDK versions to match the current Portal API
Example fix
// before
outlet.attach(this.portalDef as any); // plain object, throws
// after
import {ComponentPortal} from '@angular/cdk/portal';
outlet.attach(new ComponentPortal(this.portalDef.component)); Defensive patterns
Strategy: type-guard
Validate before calling
function isAttachablePortal(p: unknown): p is ComponentPortal<any> | TemplatePortal<any> | DomPortal {
return p instanceof ComponentPortal || p instanceof TemplatePortal || p instanceof DomPortal;
}
if (isAttachablePortal(portal)) { outlet.attach(portal); } Type guard
function isConcretePortal(v: unknown): v is ComponentPortal<any> | TemplatePortal<any> {
return v instanceof ComponentPortal || v instanceof TemplatePortal;
} Try / catch
try {
outlet.attach(portal as any);
} catch (e) {
if (e.message.includes('unknown Portal type')) {
console.error('Expected ComponentPortal/TemplatePortal, got:', portal?.constructor?.name);
} else { throw e; }
} Prevention
- Always construct concrete portal instances (new ComponentPortal/new TemplatePortal), never pass raw objects or classes
- Avoid `as any` casts that hide portal type mismatches
- When creating custom portals, extend the correct base class and test attachment
- Update custom portal subclasses after CDK upgrades
When it happens
Trigger: Passing a plain object cast as a Portal, a custom Portal subclass that does not override the type discriminator correctly, passing a `Portal` base instance instead of a concrete subclass, or an old/custom portal class from a different library version.
Common situations: DI misconfiguration returning the abstract Portal token; upgrading Angular/CDK where a custom portal no longer extends the expected class; wrapping portals in generics/proxies that erase the concrete type; typos such as passing the portal's component class instead of a ComponentPortal instance.
Related errors
- Cannot attach component portal to outlet without an Applicat
- DOM portal content must be attached to a parent node.
- DOM portal content must be attached to a parent node.
- Must provide a portal to attach
- Host already has a portal attached
AI-assisted analysis of angular/components@0411926e7d (2026-08-31).
Data as JSON: /api/errors/64543c562e3c73a0.
Report an issue: GitHub.