Angular SSR: ReferenceError: window is not defined / document is not defined / localStorage is not defined
Code that only works in a browser ran during server-side rendering, where window, document and localStorage do not exist.
ReferenceError: window is not definedReferenceError: document is not definedReferenceError: localStorage is not definedReferenceError: navigator is not definedwindow is not defined Angular SSR Meaning
Angular SSR renders on Node. Browser globals are unavailable there. Wrap browser-only code with isPlatformBrowser, run it in afterNextRender, inject DOCUMENT instead of using document directly, and use abstractions for storage. Libraries that touch window at import time need lazy import or an SSR-safe alternative.
Common causes
- Direct use of
window,document,localStorageornavigatorin components/services - Third-party library accessing
windowon import - Code in constructors or
ngOnInitrunning on the server - Using
ElementRef.nativeElementAPIs that need a real DOM - Missing platform check around analytics/maps/charts
⚡ Quick fix
- Guard with
isPlatformBrowser(inject(PLATFORM_ID)) - Move DOM work to
afterNextRender() - Inject
DOCUMENTinstead of the globaldocument
Detailed fix by platform
Angular
private platformId = inject(PLATFORM_ID); if (isPlatformBrowser(this.platformId)) { localStorage.setItem('k', 'v'); }afterNextRender(() => { this.chart = new Chart(...); });
Code examples
Browser-only code
import { PLATFORM_ID, afterNextRender, inject } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
export class ThemeService {
private platformId = inject(PLATFORM_ID);
load() {
if (isPlatformBrowser(this.platformId)) {
return localStorage.getItem('theme'); // only runs in the browser
}
return null;
}
}How to diagnose
- Global — Which global is undefined?
- Source — Own code or a library import?
- Timing — Runs at construction or after render?
🔧 Still not fixed?
Many errors look alike. If the steps above didn’t solve it, one of these is probably what you’re facing:
Similar errors
- Cannot find control with name Angular: Error: Cannot find control with name: 'email' (reactive forms)
- exceeded maximum budget Angular build: Error: bundle initial exceeded maximum budget. Budget 1.00 MB was not met by 120.00 kB with a total of 1.12 MB
- Hydration failed Error: Hydration failed because the initial UI does not match what was rendered on the server
Most viewed in Angular
Other ways to find it
Where this error sits
Origin: On your device. Errors that are often confused with or caused by this one (click to open):
🧠 Still stuck? Analyze your error
Paste the full message, response headers or stack trace — we'll detect the platform and point to the most likely cause.
💬 What worked for others
No tips yet — did something else fix this for you?
Share what worked for you
Tips are checked by an editor before they appear. Links are removed.
Report a correction or suggest an improvement
Last updated 15 Oct 2026