Angular reports NG8021 when triggers in an @defer block are unreachable or redundant. Fix it by removing ineffective prefetching, moving a prefetch timer earlier than the main timer, adding an explicit main trigger when prefetch is conditional, or making prefetch and main triggers genuinely distinct. Extended diagnostics, including NG8021, require strictTemplates to be enabled.
What NG8021 checks
NG8021 is an extended diagnostic for trigger configurations in @defer blocks that cannot work as intended or add no useful behavior. Angular identifies four patterns: on immediate combined with prefetch, a prefetch timer equal to or later than the main timer, prefetch without an explicit main trigger, and identical prefetch and main triggers. See Angular’s NG8021 diagnostic reference.
As an Amazon Associate I earn from qualifying purchases.
To emit this diagnostic, enable strictTemplates. The deferTriggerMisconfiguration diagnostic has no additional requirements.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsHow to fix each trigger pattern
Remove prefetch from an immediate block
If the main trigger is on immediate, remove the prefetch trigger. The main trigger already starts the deferred behavior immediately, so prefetch has no useful earlier opportunity.
#1 Best Overall
Schedule timer prefetch before the main timer
A prefetch timer must fire before the main timer to fetch code ahead of the main trigger. If it is equal to or later than that timer, it is redundant or too late. Angular’s example uses prefetch at 500 ms and the main trigger at 1000 ms:
@defer (on timer(1000); prefetch on timer(500)) {
<heavy-component />
}
Use values that fit the intended interaction; the key is that the prefetch delay is shorter than the main delay.
Rank #2
- Keep track of everything from attendance to test scores
- Spiral bound
- Measures 8-1/2" x 11"
Add a main trigger when prefetch is conditional
Prefetch controls fetching, not rendering. If you specify prefetch but no main trigger, the main trigger defaults to on idle. Idle can therefore start the deferred loading without waiting for the prefetch condition, which may not match the intent. Add an explicit main trigger, such as on interaction, and keep the prefetch condition separate:
@defer (on interaction; prefetch when someFlag()) {
<heavy-component />
}
In this example, the condition controls when code may be prefetched, while interaction controls the main deferred behavior.
Rank #3
Make prefetch and main triggers distinct
If prefetch and the main trigger are identical, remove the redundant prefetch or choose distinct triggers. For example, prefetch on hover over an area, then load when the user interacts with a button. The early fetch can then happen before the separate main trigger.
Understand the difference between fetching and rendering
The @defer API separates prefetching from the main trigger: prefetch configures when deferred code is fetched, while on and when conditions control the deferred content behavior. Triggers can be separated by semicolons. Built-in triggers include idle, viewport, interaction, hover, immediate, and timer; the default main trigger is idle. A when trigger supplies a custom condition.
Rank #4
Multiple event triggers act as OR conditions: any one of them can activate the behavior. A when condition is one-way; after the block swaps to deferred content, a later false value does not reverse that swap. Angular covers trigger behavior in its defer triggers tutorial.
If chunks load earlier than expected
A trigger configuration is not the only reason deferred chunks may load earlier than expected. Check the environment before changing the template.
Best Value
- Hot Module Replacement: With HMR active, Angular fetches all
@deferchunks eagerly, overriding the configured triggers. Serve with--no-hmrto observe normal trigger behavior. - SSR or SSG: By default, server rendering produces the placeholder—or nothing if no placeholder is present—without invoking defer triggers. Triggers activate on the client after the placeholder hydrates. Angular documents Incremental Hydration with hydrate triggers as the route to rendering main content on the server.
These runtime behaviors are described in Angular’s deferred loading guide.
When the issue is chunk splitting, not NG8021
A clean trigger configuration does not guarantee a separate lazy chunk. Angular’s deferred loading guide says dependencies intended for deferral must be standalone and must not also be referenced outside @defer in the same file. Imports through barrel files can also prevent a separate lazy chunk; Angular recommends direct imports. These are adjacent chunk-splitting concerns, not the trigger errors diagnosed by NG8021.
Quick Recap
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.




