LEARN · DEBUGGING GUIDE

Angular Standalone Component Import Error: What Actually Works

Standalone components break differently than NgModules. The error messages are misleading. This guide covers the real causes and fixes for import failures in standalone component trees.

IntermediateAngular9 min read

What this usually means

The Angular compiler cannot resolve a component/directive used in another component's template. With standalone components, you must explicitly import every dependency in the `imports` array of the consuming component. If you miss an import, the compiler treats the element or attribute as unknown. Also, if the imported component has `standalone: false` or is exported from an NgModule that isn't imported transitively, the same error surfaces. The error messages are notoriously generic — they don't tell you which import is missing or why.

( 01 )Fast diagnosis

The first ten minutes — establish facts before touching code.

  • 1Check the exact error: 'not a known element' means the component tag is unknown; 'Can't bind to' means a directive (like *ngIf) is missing.
  • 2Open the consuming component file and verify that the missing directive or component is listed in its `imports` array.
  • 3If the missing directive is from CommonModule (e.g., ngIf, ngFor), ensure you imported CommonModule (or BrowserModule) in the standalone component.
  • 4For a component imported from a library, verify the library's module exports the component (if it's not standalone), and import that NgModule.
  • 5Check that the imported component itself has `standalone: true` in its @Component decorator — if it's false, you must import via its NgModule.
  • 6Look for circular dependencies: if component A imports B and B imports A, Angular may silently fail.
  • 7Check the Angular version: standalone was introduced in v14. Using a standalone-only pattern in v13 or earlier causes this.
( 02 )Where to look

The specific files, logs, configs, and dashboards that usually own this bug.

  • searchThe consuming component's TypeScript file – the `@Component.imports` array.
  • searchThe imported component's `@Component` decorator – check `standalone` flag and `selector`.
  • searchThe NgModule that declares the component (if not standalone) – verify it exports the component.
  • searchpackage.json and angular.json to confirm Angular version >= 14.
  • searchangular compiler options in tsconfig.json – `strictTemplates` can mask errors.
  • searchBrowser devtools console for precise error stack trace – often points to the exact template line.
  • searchIf using lazy loading, the route configuration and feature module (if hybrid) – check imports there.
( 03 )Common root causes

Practical causes, not theory. These are the things you will actually find.

  • warningMissing import of CommonModule or BrowserModule in standalone component for *ngIf, *ngFor, etc.
  • warningImported component has `standalone: false` or is declared in an NgModule but you imported the component directly instead of the module.
  • warningTypo in component selector (e.g., `app-header` vs `appHeader`) — the error says 'not a known element' but the import is correct.
  • warningCircular dependency between standalone components — Angular silently fails to resolve them.
  • warningHybrid app (standalone + NgModules) where a standalone component tries to use a directive from an NgModule that isn't imported transitively.
  • warningLazy-loaded standalone component not imported in the route config's `loadComponent` but used in another component's template.
  • warningIncorrect import path — you imported from `../shared/header` but the file is actually `../shared/header.component`.
( 04 )Fix patterns

Concrete fix directions. Pick the one that matches your root cause.

  • buildAdd CommonModule to the `imports` array of any standalone component that uses *ngIf, *ngFor, ngSwitch, ngClass, or ngStyle.
  • buildIf the imported component is not standalone, import its NgModule (e.g., `SharedModule`) into the consuming component's `imports` array, not the component itself.
  • buildFor hybrid apps, ensure that any NgModule that declares a directive used by a standalone component is either imported directly into the standalone component or exported from a module that is imported.
  • buildUse Angular Language Service in your IDE — it catches missing imports before compilation. Run `ng serve` with `--optimization=false` to see more verbose errors.
  • buildRefactor circular dependencies: extract shared components into a separate module or file, or use forwardRef if absolutely necessary.
  • buildCheck the Angular version: if you're on v14, ensure you've enabled standalone in the bootstrap (using `provideStandalone` or `bootstrapApplication`).
  • buildRun `ng update @angular/core` to get the latest compiler fixes for standalone imports.
( 05 )How to verify

A fix you cannot prove is a guess. Close the loop.

  • verifiedAfter adding the import, run `ng serve` and confirm no template parse errors appear.
  • verifiedOpen the browser devtools and verify the component renders correctly — no blank white page.
  • verifiedRun unit tests: `ng test` — all component tests should pass without 'Unexpected directive' errors.
  • verifiedCheck the Angular compiler output in the terminal: no errors related to unknown elements or properties.
  • verifiedInspect the rendered DOM: the component element should exist with the correct attributes.
  • verifiedUse Angular DevTools profiler to confirm the component tree is correctly resolved.
  • verifiedBuild in production mode: `ng build --prod` — ensure no build-time errors.
( 06 )Mistakes to avoid

Things that make this bug worse or harder to find.

  • warningDo not blindly add `CUSTOM_ELEMENTS_SCHEMA` to suppress errors — it hides real problems and breaks template type-checking.
  • warningDo not import the same standalone component into two modules/components that create a circular dependency.
  • warningDo not assume that importing a component means its dependencies (like child components) are also available — each component must import its own dependencies.
  • warningDo not use `bootstrapModule` for a standalone component — use `bootstrapApplication` instead.
  • warningDo not ignore the error 'Unexpected directive' — it means you imported a directive that isn't exported by the module you imported.
  • warningDo not mix standalone components and NgModule declarations in the same module without understanding the rules — either fully standalone or fully module-based per component.
( 07 )War story

The Silent Blank White Page: A Standalone Import Nightmare

Senior Frontend EngineerAngular 15, standalone components, lazy-loaded routes, Angular Material

Timeline

  1. 09:15Deployed new feature: user profile page built as standalone component with child components.
  2. 10:02User reports blank white page on profile route. No console errors in production.
  3. 10:10I reproduce locally in dev mode: no error, just blank page. Check network tab — assets loaded fine.
  4. 10:20Check Angular DevTools — component tree shows <app-profile> but no children.
  5. 10:30Enable production mode locally — still no error. Suspect template parse error swallowed.
  6. 10:40Add CUSTOM_ELEMENTS_SCHEMA to profile component — page renders but with broken child components.
  7. 10:50Remove schema and check profile.component.ts imports: missing CommonModule for *ngIf in template.
  8. 11:00Add CommonModule import — page renders correctly. Root cause: CommonModule missing.

We had just rolled out a new user profile page built entirely with standalone components. The page itself was a standalone component that used several child components like <app-avatar> and <app-bio>. We lazy-loaded the profile route with loadComponent. Everything worked in our dev environment, but after deploying to production, users reported a blank white page when navigating to /profile. No error messages in the console, no failed network requests — just a white void.

I spent the first 30 minutes checking the obvious: route configuration, lazy loading syntax, Angular version compatibility. The route config looked correct: `loadComponent: () => import('./profile/profile.component').then(m => m.ProfileComponent)`. I checked the network tab: all JavaScript chunks loaded. I opened Angular DevTools and saw the profile component in the component tree, but it had no children. That was the clue: the template should have rendered child components, but they were missing.

I enabled production mode locally and still saw no error. Then I remembered: Angular suppresses template parse errors in production by default. I added `CUSTOM_ELEMENTS_SCHEMA` to the profile component — the page rendered, but the child components were broken (their templates didn't work). That confirmed a missing import. I removed the schema and carefully checked the imports array: I had imported the child component classes but forgot `CommonModule`. The template used `*ngIf` and `*ngFor`, which require CommonModule. Adding CommonModule fixed everything.

Root cause

Missing CommonModule import in the standalone profile component. The template used structural directives (ngIf, ngFor) but CommonModule was not imported, causing Angular to silently fail to render child components in production mode.

The fix

Added `CommonModule` to the `imports` array of the `ProfileComponent`. Also added `CUSTOM_ELEMENTS_SCHEMA` was removed after the fix.

The lesson

Never assume CommonModule (or BrowserModule) is automatically available in standalone components. Always import it explicitly if you use any Angular built-in directives. Also, enable `optimization: false` during development to see template errors that are suppressed in production.

( 08 )How Standalone Imports Actually Work (Compiler Perspective)

When Angular compiles a standalone component, it reads the `imports` array and treats each import as an NgModule or another standalone component/directive/pipe. The compiler then creates a compilation scope that includes all exported directives/pipes from those imports. If a template uses a directive that is not in that scope, the compiler fails with a template parse error. For standalone components, this scope is flat — there's no module hierarchy to walk. That's why missing CommonModule is so common: in NgModule-based apps, BrowserModule re-exports CommonModule, but in standalone components, you must import CommonModule directly.

The compiler's error messages are intentionally generic because the template is compiled to a set of instructions. The error 'not a known element' doesn't tell you which import is missing. You need to manually check the template and the imports array. The Angular Language Service (in VS Code or WebStorm) can catch these errors at edit time by analyzing the template and imports. It's not perfect — it can miss imports that are dynamically resolved or from libraries with complex module structures.

( 09 )Hybrid Apps: Mixing Standalone and NgModules

Many real-world apps are hybrid: some components are standalone, others are declared in NgModules. The import rules become tricky. If a standalone component wants to use a directive that is declared in an NgModule (e.g., a custom directive from SharedModule), you must import that NgModule into the standalone component's `imports` array. It's not enough to import the directive class directly — Angular expects the NgModule because the directive is not standalone. Conversely, if a component is standalone, you can import it directly into another standalone component or into an NgModule's `imports` array.

A common mistake is to import a standalone component into an NgModule's `declarations` array — that's invalid because standalone components cannot be declared in NgModules. You'll get a compiler error: 'Standalone components cannot be declared in NgModules'. Instead, add the standalone component to the NgModule's `imports` array. Also, if you have a lazy-loaded route that loads a standalone component, ensure that the route's `loadComponent` is used (not `loadChildren` with a module).

( 10 )Debugging Silent Failures: Production vs Dev

In development mode, Angular's compiler runs in JIT mode and emits detailed error messages to the console. In production mode (AOT), the compiler runs at build time and any template errors should fail the build. However, there are cases where the build succeeds but the component fails at runtime — for example, if you use `CUSTOM_ELEMENTS_SCHEMA` to suppress errors, or if the error is in a lazy-loaded component that isn't checked until it's instantiated. The blank page scenario often happens because the root component renders, but a child component fails to compile and the error is caught silently by Angular's error handler, which might not log anything if not configured.

To debug silent failures, first disable `CUSTOM_ELEMENTS_SCHEMA` if you have it. Then, in development mode, check the browser console for any Angular error messages — they may appear as 'ERROR Error: Template parse errors' in the console, even if the page is blank. Use the Angular DevTools to inspect the component tree: if a component is missing its children, that's a sign of a missing import. Also, you can temporarily set `ERROR_HANDLER` to log all errors to the console to catch swallowed errors.

( 11 )Common Pitfalls with Angular Material and Third-Party Libraries

When using Angular Material components in standalone components, you must import each Material module individually (e.g., `MatButtonModule`, `MatInputModule`) into your standalone component's `imports` array. You cannot import the entire `MatModule` — it doesn't exist. Each Material component is its own NgModule. Also, some Material components have dependencies on other Material modules (e.g., `MatTableModule` depends on `MatSortModule`). If you miss a dependency, you get a confusing error like 'Can't bind to 'matSort' since it isn't a known property'.

For other third-party libraries, check if they provide standalone-compatible exports. Many libraries now export standalone directives/pipes. If not, you need to import the library's NgModule. Also, beware of peer dependency version mismatches — Angular 15 changed the import paths for some packages. Always run `ng update` to ensure compatibility.

Frequently asked questions

Why does my standalone component work in dev but not in production?

In production, AOT compilation happens at build time. If you have a missing import that doesn't cause a build error (e.g., because you used CUSTOM_ELEMENTS_SCHEMA or the error is in a lazy-loaded component), the component may fail to render silently. Always run `ng build --prod` locally and check for errors. Also, avoid CUSTOM_ELEMENTS_SCHEMA in production code.

Can I import a standalone component into an NgModule?

Yes, you can import a standalone component into an NgModule's `imports` array (not `declarations`). The standalone component becomes available to all components declared in that NgModule. But you cannot declare a standalone component in an NgModule — that causes a compiler error.

What is the difference between importing CommonModule and BrowserModule in a standalone component?

CommonModule provides structural directives like ngIf, ngFor, ngSwitch, and ngClass/ngStyle. BrowserModule provides the same plus application-wide services like DomSanitizer. For standalone components, you almost always need CommonModule. BrowserModule should only be imported once, typically in the root component or via `provideProtractorTesting` etc. Importing BrowserModule in a child standalone component will cause an error: 'BrowserModule has already been loaded'.

How do I fix 'Unexpected directive' error?

This error means you imported a directive (or a module that exports it) but the directive is not part of the compilation scope. Check that the module you imported actually exports the directive. If the directive is standalone, import it directly. If it's from a third-party library, ensure you imported the correct NgModule that exports it.

Can I use standalone components in an Angular 13 project?

No, standalone components were introduced in Angular 14. In Angular 13, you must use NgModules. If you try to use `standalone: true`, the compiler will throw an error. Upgrade to Angular 14+ to use standalone components.