angular/angular-cli · warning
[NG HMR] Cannot find the application root component.
Error message
[NG HMR] Cannot find the application root component.
What it means
The HMR plugin's getAppRoot() locates the running application's root element by querying document.querySelector('[ng-version]') — the attribute Angular sets on the bootstrapped root component. When no element carries that attribute, HMR cannot determine the app root to re-render after an update, so it warns and returns undefined, aborting the HMR swap for the app root (newAppRoot/appRoot both depend on it).
Source
Thrown at packages/angular_devkit/build_angular/src/tools/webpack/plugins/hmr/hmr-accept.ts:129
// Wait until the application isStable to restore the form values
newAppRef.isStable
.pipe(
filter((isStable) => !!isStable),
take(1),
)
.subscribe(() => restoreFormValues(oldInputs, oldOptions));
}).observe(bodyElement, {
attributes: true,
subtree: true,
attributeFilter: ['ng-version'],
});
});
}
function getAppRoot(): any {
const appRoot = document.querySelector('[ng-version]');
if (!appRoot) {
console.warn('[NG HMR] Cannot find the application root component.');
return undefined;
}
return appRoot;
}
function getToken<T>(appRoot: any, token: Type<T>): T | undefined {
return (typeof ng === 'object' && ng.getInjector(appRoot).get(token)) || undefined;
}
function getApplicationRef(appRoot: any): ApplicationRef | undefined {
const appRef = getToken(appRoot, ApplicationRef);
if (!appRef) {
console.warn(`[NG HMR] Cannot get 'ApplicationRef'.`);
return undefined;
}View on GitHub (pinned to bb72145f9a)
Solutions
- Fix any runtime bootstrap errors visible in the console — if Angular never rendered, ng-version is never set; a hard reload after fixing the error restores HMR.
- Do a full page reload (not an HMR patch) after ng serve starts so the initial bootstrap completes before updates are applied.
- If bootstrapping into a custom element or shadow DOM, ensure the root component element with ng-version is in the light DOM, or disable HMR ("hmr": false) and use live-reload.
- Check that only one Angular application instance is bootstrapped per page and it is not destroyed before the HMR update.
- If the warning appears only during SSR/hydration, defer HMR updates until after hydration or disable HMR for that configuration.
Example fix
// before (main.ts, failing bootstrap)
platformBrowser().bootstrapModule(AppModule).catch(err => console.error(err)); // error swallowed, no ng-version in DOM
// after: surface bootstrap failures and ensure root renders
platformBrowser()
.bootstrapModule(AppModule)
.catch(err => { console.error(err); throw err; }); Defensive patterns
Strategy: fallback
Validate before calling
// Verify the Angular root element exists before/around HMR updates
function appRootPresent(doc = document) {
return Boolean(doc.querySelector('[ng-version]'));
}
if (!appRootPresent()) {
console.warn('Angular root ([ng-version]) not in DOM — HMR cannot re-render; do a full reload.');
location.reload();
} Type guard
function isBootstrappedRootElement(el) {
return el instanceof HTMLElement && el.hasAttribute('ng-version');
} Try / catch
try {
const root = document.querySelector('[ng-version]');
if (!root) throw new Error('[NG HMR] application root not found');
// proceed with HMR re-render
} catch (e) {
console.warn(String(e), '— falling back to full page reload');
location.reload();
} Prevention
- Fix console errors at startup first: an unbootstrapped app has no [ng-version] element, so every HMR update will warn.
- Avoid rendering the Angular root inside shadow DOM or a document fragment that document.querySelector cannot reach.
- Bootstrap exactly one application per page and never remove the root element manually during development.
- After starting ng serve, let the initial build/bootstrap finish (full load) before saving files that trigger HMR.
- Disable HMR ("hmr": false) if your bootstrap pattern (SSR, custom elements, micro-frontends) is incompatible with it.
When it happens
Trigger: getAppRoot() runs during an HMR update (invoked via appRoot/newAppRoot) and document.querySelector('[ng-version]') returns null — i.e. the page DOM has no element with the ng-version attribute at the moment of the hot update.
Common situations: 1) The application failed to bootstrap (runtime JS error before Angular rendered the root component), so ng-version was never set. 2) Custom bootstrap where the root selector/component differs or the app is rendered into a shadow root not visible to document.querySelector. 3) Multiple Angular apps or full page reload clearing the DOM mid-HMR. 4) SSR/hydration setups where the served HTML lacks ng-version until hydration completes. 5) HMR update arriving before initial render finished (early save after ng serve start).
Related errors
- [NG HMR] Cannot find global 'ng'. Likely this is caused beca
- [NG HMR] Unknown input type ${oldElement.type}.
- [NG HMR] Cannot restore selected options.
- Could not find ${level} workspace.
- Invalid config found at ${workspace.filePath}. CLI should be
AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30).
Data as JSON: /api/errors/3fd5b57d7d3aa009.
Report an issue: GitHub.