{"record":{"id":"64543c562e3c73a0","repo":"angular/components","slug":"attempting-to-attach-an-unknown-portal-type-basep","errorCode":null,"errorMessage":"Attempting to attach an unknown Portal type. BasePortalOutlet accepts either a ComponentPortal or a TemplatePortal.","messagePattern":"Attempting to attach an unknown Portal type\\. BasePortalOutlet accepts either a ComponentPortal or a TemplatePortal\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cdk/portal/portal-errors.ts","lineNumber":38,"sourceCode":" */\nexport function throwPortalAlreadyAttachedError() {\n  throw Error('Host already has a portal attached');\n}\n\n/**\n * Throws an exception when attempting to attach a portal to an already-disposed host.\n * @docs-private\n */\nexport function throwPortalOutletAlreadyDisposedError() {\n  throw Error('This PortalOutlet has already been disposed');\n}\n\n/**\n * Throws an exception when attempting to attach an unknown portal type.\n * @docs-private\n */\nexport function throwUnknownPortalTypeError() {\n  throw Error(\n    'Attempting to attach an unknown Portal type. BasePortalOutlet accepts either ' +\n      'a ComponentPortal or a TemplatePortal.',\n  );\n}\n\n/**\n * Throws an exception when attempting to attach a portal to a null host.\n * @docs-private\n */\nexport function throwNullPortalOutletError() {\n  throw Error('Attempting to attach a portal to a null PortalOutlet');\n}\n\n/**\n * Throws an exception when attempting to detach a portal that is not attached.\n * @docs-private\n */\nexport function throwNoPortalAttachedError() {","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/angular/components/blob/0411926e7d8ae06b32236ec1048a888cfad5abf2/src/cdk/portal/portal-errors.ts#L20-L56","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\noutlet.attach(this.portalDef as any); // plain object, throws\n// after\nimport {ComponentPortal} from '@angular/cdk/portal';\noutlet.attach(new ComponentPortal(this.portalDef.component));","handlingStrategy":"type-guard","validationCode":"function isAttachablePortal(p: unknown): p is ComponentPortal<any> | TemplatePortal<any> | DomPortal {\n  return p instanceof ComponentPortal || p instanceof TemplatePortal || p instanceof DomPortal;\n}\nif (isAttachablePortal(portal)) { outlet.attach(portal); }","typeGuard":"function isConcretePortal(v: unknown): v is ComponentPortal<any> | TemplatePortal<any> {\n  return v instanceof ComponentPortal || v instanceof TemplatePortal;\n}","tryCatchPattern":"try {\n  outlet.attach(portal as any);\n} catch (e) {\n  if (e.message.includes('unknown Portal type')) {\n    console.error('Expected ComponentPortal/TemplatePortal, got:', portal?.constructor?.name);\n  } else { throw e; }\n}","preventionTips":["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"],"tags":["angular","cdk","portal","typescript"],"backgroundTag":"unknown-portal-type","analyzedSha":"0411926e7d8ae06b32236ec1048a888cfad5abf2","analyzedAt":"2026-08-31T11:58:23.400Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}