angular/angular-cli · warning
[NG HMR] Cannot get 'PlatformRef'.
Error message
[NG HMR] Cannot get 'PlatformRef'.
What it means
A console.warn from the Angular CLI HMR helper after a hot update. The helper locates the application root element and asks ng.getInjector(appRoot).get(PlatformRef) so it can destroy the old platform before re-bootstrapping. When PlatformRef cannot be resolved from that injector, the warning fires, the old platform is left undestroyed, and the HMR state-restore flow is skipped.
Source
Thrown at packages/angular_devkit/build_angular/src/tools/webpack/plugins/hmr/hmr-accept.ts:155
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;
}
return appRef;
}
function getPlatformRef(appRoot: any): PlatformRef | undefined {
const platformRef = getToken(appRoot, PlatformRef);
if (!platformRef) {
console.warn(`[NG HMR] Cannot get 'PlatformRef'.`);
return undefined;
}
return platformRef;
}
function dispatchEvents(element: any): void {
element.dispatchEvent(
new Event('input', {
bubbles: true,
cancelable: true,
}),
);
element.blur();
element.dispatchEvent(new KeyboardEvent('keyup', { key: 'Enter' }));View on GitHub (pinned to bb72145f9a)
Solutions
- Make sure only one Angular platform instance/bootstrapped root exists on the page (guard bootstrapModule with an already-bootstrapped check).
- Disable scripts optimization in dev so the ng global matches the bundled Angular core (angular.json development: optimization.scripts = false).
- Deduplicate @angular/core across bundle and dependencies so the token instance matches.
- Disable HMR (--no-hmr) if the app uses a non-standard bootstrap that HMR cannot handle.
Example fix
// main.ts — before
platformBrowserDynamic().bootstrapModule(AppModule).catch(err => console.error(err));
// after (idempotent re-bootstrap, HMR-friendly)
if (!window['ng']) { platformBrowserDynamic().bootstrapModule(AppModule).catch(err => console.error(err)); } Defensive patterns
Strategy: validation
Validate before calling
const appRoot = document.querySelector('[ng-version]');
if (!appRoot || !(window as any).ng?.getInjector?.(appRoot)?.get) {
console.warn('[NG HMR] Platform injector not resolvable; HMR will skip re-bootstrap.');
} Type guard
function hasPlatformInjector(ng: any, appRoot: Element): boolean {
try { return !!ng?.getInjector?.(appRoot)?.get; } catch { return false; }
} Prevention
- Guard bootstrap code so the platform is not bootstrapped twice.
- Avoid mixing Angular core copies between bundles.
- Use standard bootstrapModule/bootstrapApplication entry points.
- Test HMR flow with your exact bootstrap setup before relying on it.
When it happens
Trigger: During the mod.hot.dispose callback: getToken(appRoot, PlatformRef) returns undefined because the injector found on the [ng-version] element is not the root platform injector (wrong element matched), ng.getInjector is present but stale (old destroyed app), or a single Angular core instance is not shared between the bundle and the HMR runtime.
Common situations: Multiple Angular apps or a re-bootstrap on the same page leaving a stale [ng-version] element; zoneless/experimental bootstrap setups where injector resolution differs; bundled runtime where ng global points to a different Angular core copy than the app's; scripts optimization partially enabled.
Related errors
- [NG HMR] Cannot get 'ApplicationRef'.
- Webpack stats build result is required.
- The "application" and "browser-esbuild" builders do not supp
- Only the "application" and "browser-esbuild" builders suppor
- Only the "application" and "browser-esbuild" builders suppor
AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30).
Data as JSON: /api/errors/524a63ce654ccec2.
Report an issue: GitHub.