ReferenceError: window is not defined
Next.js · updated 2026-11-03
Thrown during server rendering or the build, when code touches window, document or localStorage. Server Components and the server pass of Client Components both run in Node.js, where those globals don't exist.
⨯ ReferenceError: window is not defined
at Chart (./src/components/Chart.tsx:9:17)
at renderWithHooks (node_modules/react-dom/cjs/react-dom-server.node.development.js:5728:16)
at renderIndeterminateComponent (node_modules/react-dom/cjs/react-dom-server.node.development.js:5781:15) {
digest: '1846296187'
}Quick fix
Run browser-only code after the component mounts: inside useEffect, an event handler, or a component loaded with next/dynamic and ssr: false. A 'use client' directive alone is not enough, because Client Components still render once on the server.
- Find the line in the stack trace that reads window, document, localStorage or navigator.
- If it runs while rendering, move it into useEffect so it only runs in the browser.
- If a library touches window when it is imported, load the component that uses it with next/dynamic and ssr: false.
- For code that must run in both places, guard it with typeof window !== 'undefined'.
'use client';
import { useEffect, useState } from 'react';
import dynamic from 'next/dynamic';
// A library that reads window at import time
const Chart = dynamic(() => import('./Chart'), { ssr: false });
export function Dashboard() {
const [width, setWidth] = useState(0);
useEffect(() => setWidth(window.innerWidth), []); // runs only in the browser
return <Chart width={width} />;
}Why it happens
Assuming 'use client' means browser-only
Client Components are pre-rendered to HTML on the server and then hydrated. Anything they do in the render body, including reading window, runs on the server first.
A library that reads window at import time
Some chart, map and editor packages check window when the module loads. Importing them at the top of any file that renders on the server fails before your component code runs.
Reading localStorage or matchMedia to pick initial state
Setting useState from localStorage in the component body runs on the server. Start with a server-safe default and read the stored value in useEffect.
Other fixes
- A typeof window check in the render body avoids the crash but can cause a hydration mismatch if the server and client output differ: prefer useEffect.
- For a whole page that only works in the browser, render a shell on the server and load the interactive part with next/dynamic.
Same error, other wording
- ReferenceError: document is not defined
- ReferenceError: localStorage is not defined
- ReferenceError: navigator is not defined
Let your coding agent catch the next one
Runheed records this error in production with the stack trace, the breadcrumbs before it and the agent session that shipped the code, and serves it to Claude Code, Cursor or any MCP client. With it connected, you can ask:
> Find the window is not defined errors from server rendering, show me which component and import trigger each one, and move that code into useEffect or a dynamic import with ssr: false.
Related errors
- Hydration failed because the server rendered HTML didn't match the client. As a result...
- Error: An error occurred in the Server Components render. The specific message is omitted...
- Module not found: Can't resolve 'fs'
References: Next.js docs: Client Components, Next.js docs: lazy loading with next/dynamic