Angular Is Not A Known Element | Fixes That Work Fast

The “angular is not a known element” error means Angular can’t match a template tag to a declared, imported, or allowed element in that view.

You’re building, you hit save, and the console lights up with a wall. The message looks simple, yet it can waste an afternoon if you chase the wrong thing.

This guide walks you through the fixes that solve it in most Angular apps. You’ll start with fast checks, then move to the few cases that feel weird: standalone components, shared UI modules, and custom elements.

What The Error Means And Why It Shows Up

Angular doesn’t treat HTML templates as plain strings. It parses every tag and tries to decide what it is: a native HTML element, an Angular component selector, or a custom element that the browser will handle.

When Angular can’t validate a tag, it throws an unknown element message (often paired with error code NG8001). It’s not judging your naming style. It’s telling you the compiler can’t see a path from the template to a registered thing.

That “path” changes based on how the component is built. In NgModule-based apps, the path is declarations, imports, and exports. In standalone-based apps, the path is the component’s own imports list, plus anything brought in through route config.

Fixing The Angular Is Not A Known Element Error In Templates

Start with the element name shown in the error. Copy it, then find where it’s used. In many editors you can search the tag in one keystroke. Once you see the template, run this checklist in order.

  • Confirm the selector — Open the component you’re trying to use and check its selector value matches the tag in the template.
  • Check the owning file — Make sure you didn’t import a different component with a similar name from another folder.
  • Verify the declaration — If the component is not standalone, it must be listed in exactly one @NgModuledeclarations array.
  • Verify the import chain — The module that owns the template must import the module that exports the component you want to use.
  • Verify standalone imports — If the component is standalone, add it to the imports array of the standalone component that uses it.

Selector And Template Mismatches

Typos are still the number one cause. The error prints the tag, not the class name. If your selector is app-user-card and your template says , Angular will never connect them.

Also watch for selectors that use attributes. A selector like button[appPrimary] is used as , not . If your project uses attribute selectors, double-check how the tag is meant to appear.

NgModule Declarations, Imports, And Exports

In classic module layout, a component becomes usable only inside the module that declares it, plus any module that imports a module that exports it.

That second part is the part people skip. Declaring a component in SharedModule is not enough. You also need to export it from SharedModule, then import SharedModule from the feature module that owns the template.

// shared.module.ts
@NgModule({
  declarations: [UserCardComponent],
  exports: [UserCardComponent]
})
export class SharedModule {}

// feature.module.ts
@NgModule({
  imports: [SharedModule]
})
export class FeatureModule {}

Don’t Declare The Same Component Twice

If you try to declare the same component in two modules, Angular will complain with a different error. The fix is still related: declare it once, export it from that module, then import that module where you need it.

If you’re migrating an older codebase, search for the component class name in declarations across the project. It should appear once.

Common Causes Mapped To Fast Fixes

When you’re under time pressure, it helps to pattern-match. The table below maps what you see to what’s usually wrong.

What You Notice Likely Cause Fix To Try First
Tag is your own component selector Not declared or not exported Declare once, export it, import the module
Tag is from Angular Material Material module not imported Import the right Material module into the owning module or standalone imports
Tag is from a third-party UI kit Library module not imported Add the library module to imports where the template lives
Tag has a dash and is a browser custom element Schema blocks custom elements Add CUSTOM_ELEMENTS_SCHEMA to the module schemas, or switch to a wrapper component
Error appears only in production build AOT catches a missing export or import Check exports on the declaring module and the import chain

Standalone Components And The Imports Trap

Standalone components changed the mental model. A standalone component doesn’t live inside a module’s declarations. It carries its own dependency list in its imports array.

This is where many people trip. You can have a child component sitting right next to the parent in the same folder, and the error still happens if the parent doesn’t import the child.

// child.component.ts
@Component({
  selector: 'app-child',
  standalone: true,
  template: '

Child works

' }) export class ChildComponent {} // parent.component.ts @Component({ selector: 'app-parent', standalone: true, imports: [ChildComponent], template: '' }) export class ParentComponent {}

Pay attention to built-in directives too. In standalone land, you don’t get *ngIf, *ngFor, and pipes “for free” unless you import what provides them. That can show up as a property-binding error instead of an unknown element error, yet it has the same root cause: missing imports.

If you’re on modules, those directives usually come from CommonModule. If you’re on standalone, you can import what you use. Many teams keep it simple and add CommonModule to the component imports, then tighten it later when the template settles.

  • Add CommonModule for core directives — In module-based features, importing CommonModule brings *ngIf, *ngFor, and common pipes.
  • Import specific directives in standalone — In standalone components, you can add NgIf, NgFor, AsyncPipe, and friends directly to imports.
  • Check routing for standalone pages — If a standalone page is created through routes, its imports still control what the template can see.

One more gotcha: if your component is declared in a lazy-loaded feature module, importing that feature module into AppModule won’t make the component visible everywhere. Visibility flows to templates only through the module that owns the template, not through the root.

If your app mixes module-based and standalone pieces, keep a clear rule. A non-standalone component goes in a module’s declarations. A standalone component goes in imports lists, never declarations.

Third-Party Tags, Web Components, And Schemas

Sometimes the tag is not an Angular component at all. Web components use custom element names that include a dash, like . Angular can render them, yet its template validator needs permission to accept them.

Two checks save a lot of confusion. First, confirm the custom element is actually registered in the browser before Angular renders the template. Second, confirm you imported any Angular wrapper module the library provides. Some UI kits ship both a custom element bundle and an Angular wrapper, and mixing the two leads to head-scratching errors.

  • Load the custom element script — Add the vendor bundle in your build or import it once at app startup so the tag is defined.
  • Confirm the element name includes a dash — Browser custom elements must use a dash, so is not valid as a custom element name.
  • Prefer the vendor’s Angular entry — If the library ships an Angular module or standalone exports, use that path instead of schemas.

Using CUSTOM_ELEMENTS_SCHEMA The Right Way

CUSTOM_ELEMENTS_SCHEMA tells Angular it’s okay to see dash-case elements and dash-case properties in templates inside that module. Use it when you’re actually embedding a custom element, not to hide a missing import.

// app.module.ts (or a feature module)
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';

@NgModule({
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppModule {}

Why NO_ERRORS_SCHEMA Is A Last Resort

NO_ERRORS_SCHEMA lets any element and any property pass template checks. That can mask real mistakes, like a misspelled input binding or a wrong event name. If you reach for it, pause and make sure you’re not hiding a real wiring bug.

If the tag is from a library, the clean fix is still importing the library module, or importing the standalone component, where the template lives. Schemas are for cases where Angular truly can’t know the element.

Build And Tooling Checks That Save Hours

Once your imports and declarations are right, the error should vanish on the next build. If it doesn’t, you’re usually looking at stale build output, a path mistake, or a mismatch between what you run locally and what CI builds.

If your editor shows the error while the app still runs, you’re seeing template checking from the language tooling. That’s a good thing. It catches wiring mistakes before runtime. Treat it like a test failure, not a styling nit.

  • Restart the dev server — Stop ng serve, start it again, and watch for the first compile output.
  • Rebuild from scratch — Run ng build to force a full compile, not just an incremental one.
  • Check barrel exports — If you import from an index.ts, make sure it exports the component you think it does.
  • Check file casing — On some systems, UserCard and usercard are different paths. A build server might be stricter than your machine.
  • Inspect the error location — The line and column often point to the exact template that owns the problem.

If the message shows up only after a refactor, look for circular imports. A circular chain can cause a component symbol to be undefined at build time, which can cascade into missing declarations or missing imports.

Prevent The Error In New Code

You can avoid this class of bug with a few habits that keep dependencies obvious. None of this is fancy. It’s the boring stuff that pays off when the app grows.

  • Keep shared UI in one place — Put reusable components in a shared area, then export them from a single shared module or a small set of standalone exports.
  • Name selectors predictably — A consistent prefix and dash-case selector makes search and review faster.
  • Import close to use — In standalone components, keep the imports array short and local to the template’s needs.
  • Test templates — A simple component test that compiles the template will catch missing imports before you ship.
  • Don’t silence errors — Use schemas only when the tag is truly not an Angular component.

If you’ve fixed the wiring and you still see “angular is not a known element”, step back and confirm you’re looking at the right project and the right build command. It sounds silly, yet it happens with monorepos and multi-app workspaces.

Once you build the habit of tracing a template tag back to its declaration or import, this error turns from a blocker into a two-minute fix.