Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Angular’s ahead-of-time (AOT) compiler rejects a decorator value, a referenced symbol, or a constructor parameter when it cannot determine that value from the source code at build time. The fix depends on the exact message. “Expression form not supported”, “Reference to a local (non-exported) symbol”, “Could not resolve type”, and “Unsupported enum member name” each point to a different cause, so read the message before changing anything. Clearing caches or reinstalling packages will not resolve a metadata error.

What the AOT compiler is checking

AOT compilation runs during the build, not in the browser. The compiler has to understand every piece of decorator metadata, such as @Component, @NgModule, and @Injectable arguments, before the application runs. That is why a construct that works in ordinary TypeScript can fail inside a decorator. Metadata is held to a stricter, static subset of the language. Angular’s AOT compilation guide states the rule directly: “You write metadata in a subset of TypeScript that must conform to the following general constraints.”

Angular describes three AOT phases. Code analysis collects source and decorator metadata. Code generation interprets that metadata and produces the output the application runs. Template type checking validates binding expressions in templates. Each phase reports errors differently, so the phase is the first thing to identify.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Start with the exact message

Use the table to find the layer that owns the error, then go to the matching section below.

Message or pattern Phase and what to inspect Where to look below
Expression form not supported Code analysis. The decorator value uses syntax outside the metadata subset. Unsupported expressions
Reference to a local (non-exported) symbol Code generation. Generated code cannot reach a symbol declared in a local scope. Local and non-exported symbols
Could not resolve type Code analysis or DI. A constructor parameter type has no runtime injection token. Ambient types and injection tokens
NG2003 (missing token) Dependency injection. A primitive or Object constructor parameter type has no provider. NG2003 missing token
Unsupported enum member name Code analysis. An enum member name is not a plain, statically known name. Enum member names
Errors reported during a library build with strictMetadataEmit Library metadata emission. The option validates .metadata.json output. Library builds and strictMetadataEmit
Template binding errors Template type checking. The fault is in the template expression or its types. Template errors are a different phase

Unsupported expressions in decorator metadata

The “Expression form not supported” error means the compiler found syntax it cannot evaluate statically. Angular’s AOT metadata errors guide lists constructs such as typeof and computed property names, which are valid in ordinary code but not in metadata expressions. Tagged template expressions are also excluded. The guide states: “The AOT compiler does not support tagged template expressions; avoid them in metadata expressions.”

The supported forms in Angular’s AOT guide include:

  • Literal objects and arrays, with supported array spreads
  • Function calls, new expressions, and property access
  • Array indexing and references to identifiers that are exported
  • Template strings and literal values
  • Selected prefix and binary operators, conditional expressions, and parentheses

To repair the error, replace the unsupported construct with one of these forms, or move the dynamic work out of the decorator. For example, a computed key in a decorator value can usually be written as a literal key:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
// Fails: computed property name inside metadata
const ROLE = 'role';
@Component({
  selector: 'app-badge',
  template: '...',
  host: { [ROLE]: 'status' }
})

// Works: literal property name
@Component({
  selector: 'app-badge',
  template: '...',
  host: { 'role': 'status' }
})

Example code is illustrative. Confirm the exact construct against the current guide for your Angular version.

Local and non-exported symbols

“Reference to a local (non-exported) symbol” appears when metadata refers to a value declared inside a function or module scope that the generated code cannot access. Generated code is emitted into a separate module, so it cannot reach that binding. Angular’s AOT metadata errors guide separates two situations, and the correct fix depends on which one you have.

When Angular must know the value at build time

Values such as a component template must be known during compilation. Exporting the symbol does not solve this, because an export does not make an unknown compile-time value available. Give the constant a statically evaluable initializer, a literal or a simple expression Angular can fold at build time.

When generated code needs a runtime reference

If the generated code only needs to refer to the symbol at runtime, exporting it can work. Export the specific symbol that is needed. Avoid the blanket fix of exporting everything, which widens the public surface of a module without addressing the cause.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Destructured bindings

Angular also rejects exported destructured variables or constants when the template compiler references the destructured binding. If a configuration object is destructured into a constant, change the metadata to refer to the original object property directly. For example, write configuration.foo rather than binding foo through destructuring.

Ambient types and injection tokens

“Could not resolve type” usually appears when a constructor parameter is typed with an ambient type, a type that exists only in TypeScript declarations and has no runtime value for Angular to inject. The guide’s example is Window. TypeScript understands the type, but the Angular compiler cannot infer an injection token from it.

The documented repair is to define an InjectionToken, supply the runtime object through a factory, and inject the token with @Inject. A minimal version looks like this:

import { Inject, Injectable, InjectionToken } from '@angular/core';

export const WINDOW = new InjectionToken<Window>('window', {
  providedIn: 'root',
  factory: () => window
});

@Injectable({ providedIn: 'root' })
export class LayoutService {
  constructor(@Inject(WINDOW) private win: Window) {}
}

The factory runs in the browser, so this pattern is appropriate when the code path is only reached on the client. For server-rendered applications, check how the factory behaves where window does not exist.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

NG2003 missing token

NG2003 is a related but separate dependency injection error. It appears when a constructor parameter has a primitive type such as string, number, or boolean, or the type Object. These types have no provider, so Angular cannot find a token to inject. Replace the parameter with a class or an InjectionToken that has a provider, or pass the primitive value through a provided token. The NG2003 reference page describes the error, and the dependency injection troubleshooting guide covers how to trace providers.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Enum member names

“Unsupported enum member name” means the compiler could not read an enum member’s name as a plain, statically known name. Computed member names fall into this category. Use literal member names, with literal initializers, in any enum that is referenced from decorator metadata or from a template. The message identifies the enum member, so start there.

Library builds and strictMetadataEmit

The strictMetadataEmit option is a library setting. When it is enabled and metadata emission is active, it reports errors into emitted metadata, so problems can show up during a library build. Angular’s compiler options reference describes it as a way to validate the .metadata.json files shipped with libraries. A problem can surface even when the application that consumes the library would not report it until it uses that symbol in an annotation.

Do not treat this option as a general fix for an application’s source error. If you are building an application rather than a library, the cause is usually in one of the sections above. Change the option only when you understand its library-oriented purpose.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Template errors are a different phase

Template type checking is a separate phase from metadata collection and code generation. A binding error in a template should be fixed in the template expression or the types it uses, not by rewriting decorator metadata. Read the file and location in the diagnostic first. Angular may report a generated template file rather than a handwritten .ts file, so interpret the context before assuming where the fault lies.

What the official guidance does and does not establish

Angular’s documentation provides compiler rules, configuration guidance, and examples. It does not publish a figure for how often AOT metadata errors occur, so no frequency claim is made here. The steps above follow the current Angular documentation, but they have not been checked against a specific Angular release or project. Confirm exact syntax and option behavior in the documentation for the version your project uses.

“

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.