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

  1. 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.
  2. Do a full page reload (not an HMR patch) after ng serve starts so the initial bootstrap completes before updates are applied.
  3. 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.
  4. Check that only one Angular application instance is bootstrapped per page and it is not destroyed before the HMR update.
  5. 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

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


AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30). Data as JSON: /api/errors/3fd5b57d7d3aa009. Report an issue: GitHub.