Router-Outlet Is Not A Known Element | Fix In Minutes

router-outlet is not a known element shows up when Angular can’t see the Router features in the place you used .

You add a route, drop a into a layout, hit save… and Angular throws NG8001. Annoying, right? Most times this message comes from wiring, not a deep bug. Line up routing where your template lives and it goes away.

You’ll get quick checks, step-by-step fixes, and a reusable checklist for NgModule apps, standalone apps, lazy loading, tests, and libraries.

Why This Error Shows Up

Angular validates templates at build time. When it sees a tag it doesn’t recognize as HTML, it tries to match it to a component or directive that’s available to the current compilation context. If that context doesn’t include the Router bits that declare , Angular flags the element as unknown and stops.

That “current context” is the part that trips people up. In Angular, what a template can use depends on where that template is declared, and what that declared thing imports. If your template belongs to a component that never imports routing, won’t be visible there, even if some other file in the app imports routing.

What Angular Is Looking For

The Router exposes as a directive. In older, NgModule-based apps, it becomes available when the module that declares your component imports RouterModule. In standalone apps, it becomes available when the component imports RouterOutlet (or imports RouterModule) and your app bootstraps routing with provideRouter.

Quick Signals That Point To The Root Cause

  • Error shows in AppComponent — Your root setup is missing RouterModule (NgModule) or RouterOutlet + provideRouter (standalone).
  • Error shows in a feature layout — The feature module or standalone component doesn’t import routing bits.
  • Error shows only in tests — TestBed isn’t importing RouterTestingModule or RouterModule, so the template compiles without routing.

Router-Outlet Is Not A Known Element In Angular Apps

If you’re seeing “router-outlet is not a known element” in your build output, start by identifying which file owns the template that contains . The error message usually includes a component name and an HTML file (or inline template). That component is the place to fix, not a random shared module.

Next, check your project style. Angular projects created in recent years often use standalone components by default, while many existing apps still use NgModules. The fix is different in each style, so it helps to confirm what you’re working with before you change anything.

How To Tell Which Style You Have

  • Look for “standalone: true” — If your component decorator includes it, the component owns its own imports.
  • Look for app.module.ts — If you have a root module with declarations/imports, you’re in NgModule land.
  • Look at main.ts — If it uses bootstrapApplication, it’s standalone bootstrapping. If it uses platformBrowserDynamic().bootstrapModule, it’s NgModule bootstrapping.

Fixing Router Outlet Not A Known Element Error Step By Step

This section walks through the fixes in the order that saves the most time. Start with the style that matches your app, apply the steps, then rebuild. During migration, keep one pattern per feature.

Fix In A Classic NgModule App

In NgModule apps, the rule is simple. The module that declares the component using must import RouterModule. A shared routing module works too if it exports RouterModule and the declaring module imports it.

  1. Open The Declaring Module — Find the module that lists your component in declarations.
  2. Import RouterModule — Add RouterModule to the module’s imports array.
  3. Export RouterModule When Sharing — If you use a routing module, export RouterModule from it.
  4. Rebuild From A Clean State — Stop the dev server and run it again so the compiler resets.
// app.module.ts (or the feature module that declares the layout)
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';

@NgModule({
  imports: [
    RouterModule
  ]
})
export class AppModule {}

Fix In A Standalone App

Standalone apps shift the import responsibility to the component. You can make available by importing RouterOutlet into the component that uses it. Then set up routes at bootstrap with provideRouter (or importProvidersFrom).

  1. Import RouterOutlet In The Layout Component — Add it to the component’s imports array.
  2. Confirm Routes Are Provided — In your bootstrap file, provideRouter(routes) must run once.
  3. Restart The Dev Server — A restart catches stale build state after routing changes.
// app.component.ts (standalone)
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet],
  template: ''
})
export class AppComponent {}
// main.ts (standalone bootstrap)
import { bootstrapApplication } from '@angular/platform-browser';
import { provideRouter } from '@angular/router';
import { routes } from './app/app.routes';
import { AppComponent } from './app/app.component';

bootstrapApplication(AppComponent, {
  providers: [provideRouter(routes)]
});

Fix When Routing Lives In A Separate File

Some apps keep routes in a dedicated file and import them into a routing module or into main.ts. That’s fine. The thing to verify is that the file actually exports a routes array and that it matches the type Angular expects. A broken export can send you chasing the wrong file.

  • Check The Export Name — If main.ts imports routes, the routes file must export routes.
  • Check The Type — Use Routes from @angular/router so the compiler catches typos early.
  • Keep The File Pure — Avoid side effects in the routes file; keep it as a plain export.

Common Places People Miss The Import

Once routing is set up once, you can still hit this error later when you add a new layout, create a feature area, or move templates around. These are the spots where the import gap shows up most often.

Feature Modules With Their Own Layout

If a feature module declares a layout component that includes for child routes, that feature module needs RouterModule too. Importing RouterModule only in the root module won’t make it visible inside a separate compilation context.

  • Import RouterModule In The Feature Module — Put it next to CommonModule in the feature module imports.
  • Use RouterModule.forChild For Routes — Keep route config scoped to the feature module.
  • Keep The Layout In The Same Feature — Moving the layout into a shared module changes where it must be imported.

Standalone Feature Components

Standalone components don’t inherit imports from a parent component. Each standalone component needs its own imports list. If a feature layout is standalone and uses , it must import RouterOutlet even if the root layout already does.

Unit Tests And Shallow Renders

Tests compile templates too. If you render a component that contains in TestBed, you need a Router-aware test import. RouterTestingModule is built for this use, and it keeps navigation quiet during tests.

  1. Add RouterTestingModule — Import it in TestBed imports for the spec file.
  2. Stub Routes If Needed — Provide a tiny route list when the component expects navigation.
  3. Watch For Standalone Specs — In standalone tests, also add RouterOutlet in component imports when you compile the component directly.

Table Of Causes And Fast Fixes

Use this table to match the error to the file you’re working in.

Where It Fails Most Likely Cause Fix To Try
AppComponent template Router not set up at root Import RouterOutlet (standalone) or RouterModule (NgModule), then provide routes
Feature layout template Routing not imported in that feature Import RouterModule in the feature module, or import RouterOutlet in the standalone layout
Only during tests TestBed missing router setup Import RouterTestingModule, then compile again
After moving components Template now belongs to a different module Fix imports in the new declaring module or standalone component
Library component Library module not exporting RouterModule Export RouterModule from the library module, or document RouterOutlet import for standalone use

Edge Cases That Waste Time If You Miss Them

If the standard fixes don’t clear it, one of these edge cases is often the reason.

Typos And Wrong Tag Names

Angular treats as a specific selector. A missing dash, extra space, or a self-closing variant inside certain templates can trip you up.

  • Use The Exact Tag — Write in templates.
  • Avoid Uppercase — Keep it lowercase; Angular selectors are case-sensitive in practice.
  • Check Copy-Paste Artifacts — Hidden characters from editors can break tags.

Mixing Standalone And NgModules Mid-Feature

Angular allows interop, yet it’s easy to end up with a layout declared in a module, a child route declared in a standalone file, and a test that compiles only one side. When things get tangled, fix the ownership first: decide whether the layout is module-based or standalone, then align the imports with that choice.

  1. Pick One Owner For The Layout — Either keep it in a module or mark it standalone.
  2. Align Routes With The Owner — Use RouterModule.forChild in module features, or child route arrays in standalone features.
  3. Re-run The Build Clean — Delete the output folder if your setup keeps stale artifacts.

Using RouterOutlet Inside A Library

If you publish a library component that contains , consumers need routing available where that component is declared. For module-based libraries, export RouterModule from the library module. For standalone libraries, document that consumers must import RouterOutlet in the consuming component, since imports are local.

Template Compilation In A Different Build Target

Sometimes the app build passes, then a separate target fails: server rendering or a test runner. Trace which entry file that target uses and confirm routing setup there too.

A Clean Checklist You Can Keep And Reuse

Once you fix this once, you’ll want a repeatable way to avoid it on the next app. Use this checklist when you add routing, add a new layout, or migrate between module-based and standalone styles.

  1. Find The Template Owner — Start with the component named in the error, not a random shared file.
  2. Match The App Style — NgModule components rely on module imports; standalone components rely on component imports.
  3. Import The Right Router Piece — RouterModule for modules, RouterOutlet for standalone templates.
  4. Provide Routes Once At Bootstrap — Standalone apps need provideRouter(routes) in the bootstrap config.
  5. Scope Feature Routes Properly — Use forChild in module features, and child route arrays in standalone features.
  6. Fix Tests Alongside App Code — Add RouterTestingModule or RouterOutlet so the spec compiles templates the same way.
  7. Restart After Large Routing Changes — A full restart catches stale compiler state and clears false negatives.

If you’re stuck, search your project for RouterOutlet and RouterModule then follow the import chain to the template.

If you hit this error again, the fastest path is to repeat two questions: where is used, and what imports are visible to that template? Answer those, then the fix tends to be a single import line and a clean rebuild.

Want official reference pages? These two links show the directive itself and routing with outlets: RouterOutlet API and Routing With Outlets.